import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react';
import { Canvas } from '@react-three/fiber';
import { Box, Text, useGLTF, useTexture, useFBX } from '@react-three/drei';
import type { Group } from 'three';
import { useFrame, useThree } from '@react-three/fiber';
import { Vector3, Euler, DoubleSide } from 'three';
import * as THREE from 'three';
import { SkeletonUtils } from 'three-stdlib';
import type { GLTF } from 'three-stdlib';
import { useNavigate } from 'react-router-dom';
import './look.css';
import { baiduInstance, tsnInstance } from '../../api/instance';

// 碰撞用AABB类型（仅XZ平面）
type WallAABB = { minX: number; maxX: number; minZ: number; maxZ: number };
// 迷宫已移除
type CorridorArtwork = {
  position: [number, number, number];
  rotation: [number, number, number];
  url: string;
  title: string;
};

// 可替换为你的数字人模型地址
const AVATAR_URL = 'https://models.readyplayer.me/68d5ec283f253007467a4b34.glb';
// 为每个展品生成专属解说词
const buildArtworkIntro = (rawTitle: string): string => {
  const title = (rawTitle || '').trim();
  const t = title.toLowerCase();

  if (t.includes('甜心格格') || t.includes('tianxin') || t.includes('gege')) {
    return '《甜心格格》是一部古风轻喜动画，讲述机灵可爱的格格在皇城里的成长与趣事。画风明快，人物性格鲜明，适合亲子共赏。';
  }
  if (t.includes('房') || t.includes('fang') || t.includes('room')) {
    return '这是一件室内房间模型：以简洁的空间结构呈现温暖灯光与材质层次，强调居住氛围与临场感。请留意墙面与地面的光影过渡。';
  }
  if (t.includes('nezha') || t.includes('哪吒')) {
    return '哪吒主题插画，取材自传统神话人物，融合现代色彩语言，表现少年的叛逆与守护。动态线条与烈焰配色形成强烈视觉冲击。';
  }
  if (t.includes('flower') || t.includes('花')) {
    return '花卉主题作品：通过高饱和色块与柔和高光，表现花瓣的层次与生命力，整体氛围明快而富有生机。';
  }
  if (t.includes('cat') || t.includes('猫')) {
    return '猫咪主题插画：捕捉动物神态与毛发质感，以温暖的配色营造治愈氛围，适合作为治愈系小品欣赏。';
  }
  if (t.includes('color') || t.includes('色')) {
    return '色彩实验作品：以对比与互补关系为核心，探索冷暖平衡与节奏韵律，适合近距离观察笔触与过渡。';
  }
  if (t.includes('work') || t.includes('办公')) {
    return '工作主题插画：描绘现代办公场景的秩序与效率，以简洁几何形构建画面，强调空间层次与功能分区。';
  }
  if (t.includes('shan') || t.includes('山')) {
    return '山景主题作品：以留白与层层叠色营造远近关系，体现东方山水的意境与呼吸感。';
  }
  if (t.includes('shui') || t.includes('水')) {
    return '水的主题：通过流动的高光与反射，展现水面的节律与透明质感，整体气息清澈宁静。';
  }
  if (t.includes('he') || t.includes('河') || t.includes('river')) {
    return '河流主题作品：以蜿蜒的走向引导视线，水岸植被与倒影共同塑造节奏与层次。';
  }
  if (t.includes('yang') || t.includes('羊') || t.includes('sheep')) {
    return '牧场与羊的主题：柔软的体块与温润的毛发质感，配合草地的颗粒笔触，营造静谧乡野气息。';
  }
  if (t.includes('mi') || t.includes('米') || t.includes('rice')) {
    return '关于“米”的视觉作品：以纹理与颗粒表达朴素的日常美学，强调食物与生活的连接。';
  }
  if (t.includes('nv') || t.includes('女') || t.includes('girl') || t.includes('woman')) {
    return '人物肖像：通过面部光影与皮肤冷暖对比刻画情绪与个性，推荐近距离观察笔触变化。';
  }
  if (t.includes('dian') || t.includes('点') || t.includes('dot')) {
    return '抽象“点”系列：以点的聚散、密度与节奏构建画面秩序，强调观看过程中的呼吸与停顿。';
  }
  // 默认描述
  return `${title}：这件作品具备鲜明的视觉特点，建议从色彩、结构与质感三方面细细体会。`;
};

// 为铭牌生成"主题类别"标签
const buildThemeLabel = (rawTitle: string): string => {
  const t = (rawTitle || '').toLowerCase();
  if (t.includes('甜心格格') || t.includes('tianxin') || t.includes('gege')) return '国风动画主题';
  if (t.includes('room') || t.includes('房') || t.includes('fang')) return '室内建筑模型';
  if (t.includes('nezha') || t.includes('哪吒')) return '神话人物主题';
  if (t.includes('flower') || t.includes('花')) return '花卉主题作品';
  if (t.includes('cat') || t.includes('猫')) return '动物主题作品';
  if (t.includes('color') || t.includes('色')) return '色彩实验主题';
  if (t.includes('work') || t.includes('办公')) return '日常场景主题';
  if (t.includes('shan') || t.includes('山')) return '山景主题作品';
  if (t.includes('shui') || t.includes('水')) return '水域主题作品';
  if (t.includes('tian') || t.includes('天') || t.includes('sky')) return '天空主题作品';
  if (t.includes('he') || t.includes('河') || t.includes('river')) return '河流主题作品';
  if (t.includes('yang') || t.includes('羊') || t.includes('sheep')) return '牧场主题作品';
  if (t.includes('mi') || t.includes('米') || t.includes('rice')) return '生活素材主题';
  if (t.includes('nv') || t.includes('女') || t.includes('girl') || t.includes('woman')) return '人物肖像主题';
  if (t.includes('dian') || t.includes('点') || t.includes('dot')) return '抽象几何主题';
  return '综合主题作品';
};
// ===== Baidu TTS =====
const BAIDU_API_KEY = 'aDHfpPLPPYGpE7JQce99t7io';
const BAIDU_SECRET_KEY = 'p0JlXJQVfNip1e8h6JfAVGOLoqLqI9FC';

const getTTSToken = async (): Promise<string> => {
  const cached = localStorage.getItem('baidu_tts_token');
  const expStr = localStorage.getItem('baidu_tts_token_expire');
  const now = Math.floor(Date.now() / 1000);
  if (cached && expStr && now < Number(expStr) - 60) return cached;
  const url = `/oauth/2.0/token?grant_type=client_credentials&client_id=${encodeURIComponent(BAIDU_API_KEY)}&client_secret=${encodeURIComponent(BAIDU_SECRET_KEY)}`;
  const { data } = await baiduInstance.get(url);
  if (!data?.access_token) throw new Error(data?.error_description || 'get token failed');
  const expire = now + Number(data.expires_in || 2592000);
  localStorage.setItem('baidu_tts_token', data.access_token as string);
  localStorage.setItem('baidu_tts_token_expire', String(expire));
  return data.access_token as string;
};

const synthesizeSpeech = async (text: string): Promise<Blob> => {
  console.log('开始TTS合成，文本:', text);
  try {
    const tok = await getTTSToken();
    console.log('获取到TTS token');
    // POST application/x-www-form-urlencoded
    const params = new URLSearchParams();
    params.append('tex', text);
    params.append('tok', tok);
    params.append('cuid', 'digital-human-demo');
    params.append('ctp', '1');
    params.append('lan', 'zh');
    params.append('spd', '5');
    params.append('pit', '5');
    params.append('vol', '7');
    params.append('per', '3');
    params.append('aue', '3');
    console.log('发送TTS请求...');
    const res = await tsnInstance.post('', params, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, validateStatus: () => true });
    console.log('TTS请求响应状态:', res.status);
    const ct = (res.headers['content-type'] as string) || '';
    console.log('响应内容类型:', ct);
    if (res.status >= 200 && res.status < 300 && ct.includes('audio')) {
      console.log('TTS合成成功');
      return res.data as Blob;
    }
    try {
      const txt = await (res.data as Blob).text();
      const j = JSON.parse(txt);
      console.error('TTS错误响应:', j);
      throw new Error(j.err_msg || txt);
    } catch {
      throw new Error(`TTS failed, status ${res.status}`);
    }
  } catch (error) {
    console.error('TTS合成过程中出错:', error);
    throw error;
  }
};
// 预加载模型（非 hook，安全）
useGLTF.preload(AVATAR_URL);

// 展品组件
const Artwork: React.FC<{
  position: [number, number, number];
  rotation?: [number, number, number];
  imageUrl: string;
  title?: string;
  description?: string;
  size?: number;
  onSpeak?: (text: string) => void;
}> = ({ position, rotation = [0, 0, 0], imageUrl, title = '', size = 1, onSpeak }) => {
  console.log('Artwork 组件加载纹理:', imageUrl);
  const texture = useTexture(imageUrl);
  console.log('Artwork 纹理加载成功:', texture);
  const handleClick = () => {
    console.log('展品被点击:', title);
    if (!onSpeak) {
      console.log('onSpeak 函数不存在');
      return;
    }
    const intro = buildArtworkIntro(title);
    console.log('生成的介绍文本:', intro);
    onSpeak(intro);
  };
  return (
    <group position={position} rotation={rotation} onClick={handleClick}>
      {/* 现代画框 - 白色金属边框，背面紧贴墙面 */}
      <Box args={[2.8 * size, 2.2 * size, 0.15]} position={[0, 0, 0.075]} castShadow>
        <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.3} />
      </Box>

      {/* 画作（用平面贴图，确保显示原图纹理） */}
      <mesh position={[0, 0, 0.205]} castShadow={false} receiveShadow={false}>
        <planeGeometry args={[2.4 * size, 1.8 * size]} />
        <meshBasicMaterial map={texture} side={DoubleSide} toneMapped={false} />
      </mesh>

      {/* 简化射灯照明 */}
      <spotLight position={[0, 1.6 * size, 0.8]} angle={0.4} intensity={0.8} color={0xffffff} />

      {/* 现代展签 - 白色背景 + 蓝色文字 */}
      <group position={[0, -1.4 * size, 0.25]}>
        <Box args={[2.0 * size, 0.4 * size, 0.03]}>
          <meshStandardMaterial color="#8B4513" roughness={0.4} metalness={0.0} />
        </Box>
        <Text
          position={[0, 0, 0.031]}
          fontSize={0.18 * size}
          color="#3b82f6"
          anchorX="center"
          anchorY="middle"
        >
          {buildThemeLabel(title)}
        </Text>
      </group>
    </group>
  );
};

// 视角与构图参数
const CAMERA_HEIGHT = 1.75; // 贴近头部视角
const AVATAR_FOLLOW_DISTANCE = 1.2; // 贴背视角距离（增加距离，减少抖动）
const AVATAR_FOLLOW_DISTANCE_FULL = 2.8; // 全身视图距离（增加距离，减少抖动）

// 第三人称主角控制器（角色为权威，摄像机仅跟随）
const FirstPersonController: React.FC<{
  position: Vector3;
  rotation: Euler;
  onPositionChange: (position: Vector3) => void;
  onRotationChange: (rotation: Euler) => void;
  walls: WallAABB[];
  playerRadius?: number;
  onToggleFullBody?: () => void;
  onMovementChange?: (isMoving: boolean) => void;
  onRunChange?: (isRunning: boolean) => void;
  onBackwardChange?: (isBackward: boolean) => void;
  onLeftTurn?: () => void;
  onRightTurn?: () => void;
  onJump?: () => void;
}> = ({ position, rotation, onPositionChange, onRotationChange, walls, playerRadius = 0.3, onToggleFullBody, onMovementChange, onRunChange, onBackwardChange, onLeftTurn, onRightTurn, onJump }) => {
  const baseMoveSpeed = 0.1;
  const runMultiplier = 1.8;
  const rotationSpeed = 0.0025; // 提高灵敏度，减少延迟
  const rotationSmooth = 0.25; // 提高平滑系数，减少延迟

  const keys = useRef({
    w: false,
    s: false,
    a: false,
    d: false,
    shift: false,
    _lastMovingState: false
  });

  const mouseRef = useRef({ x: 0, y: 0 });
  const isMouseDown = useRef(false);

  // 使用 yaw/pitch 以避免倾斜，保持 z 轴为 0
  const yawRef = useRef(0);
  const pitchRef = useRef(0);
  const targetYawRef = useRef(0);
  const targetPitchRef = useRef(0);

  // 初始化 yaw/pitch
  useEffect(() => {
    // 从传入的 rotation 读取初始角
    const initial = rotation.clone();
    initial.order = 'YXZ';
    yawRef.current = initial.y;
    pitchRef.current = initial.x;
    targetYawRef.current = initial.y;
    targetPitchRef.current = initial.x;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      switch (event.key.toLowerCase()) {
        case 'w': keys.current.w = true; break;
        case 's':
          keys.current.s = true;
          if (onBackwardChange) onBackwardChange(true);
          break;
        case 'a':
          // 一次性左转：仅在按下触发，不进行侧移
          if (!event.repeat) {
            // 左转 90 度（可调整）
            const leftAngle = Math.PI / 2;
            targetYawRef.current += leftAngle;
            if (onLeftTurn) onLeftTurn();
          }
          break;
        case 'd':
          // 一次性右转：仅在按下触发，不进行侧移
          if (!event.repeat) {
            const rightAngle = -Math.PI / 2;
            targetYawRef.current += rightAngle;
            if (onRightTurn) onRightTurn();
          }
          break;
        case 'shift':
          keys.current.shift = true;
          if (onRunChange) onRunChange(true);
          break;
        case 'f':
          if (onToggleFullBody) {
            onToggleFullBody();
          }
          break;
        case ' ':
          if (onJump) {
            onJump();
          }
          break;
      }
    };

    const handleKeyUp = (event: KeyboardEvent) => {
      switch (event.key.toLowerCase()) {
        case 'w': keys.current.w = false; break;
        case 's':
          keys.current.s = false;
          if (onBackwardChange) onBackwardChange(false);
          break;
        case 'a': keys.current.a = false; break;
        case 'd': keys.current.d = false; break;
        case 'shift':
          keys.current.shift = false;
          if (onRunChange) onRunChange(false);
          break;
      }
    };

    const handleMouseDown = (event: MouseEvent) => {
      isMouseDown.current = true;
      mouseRef.current.x = event.clientX;
      mouseRef.current.y = event.clientY;
    };

    const handleMouseUp = () => {
      isMouseDown.current = false;
    };

    const handleMouseMove = (event: MouseEvent) => {
      if (!isMouseDown.current) return;

      const deltaX = event.clientX - mouseRef.current.x;
      const deltaY = event.clientY - mouseRef.current.y;

      // 更新目标 yaw/pitch（不直接设置相机，避免卡顿）
      targetYawRef.current -= deltaX * rotationSpeed;
      targetPitchRef.current -= deltaY * rotationSpeed;
      // 限制俯仰角，防止翻转
      const limit = Math.PI / 2 - 0.001;
      if (targetPitchRef.current > limit) targetPitchRef.current = limit;
      if (targetPitchRef.current < -limit) targetPitchRef.current = -limit;

      mouseRef.current.x = event.clientX;
      mouseRef.current.y = event.clientY;
    };

    window.addEventListener('keydown', handleKeyDown);
    window.addEventListener('keyup', handleKeyUp);
    window.addEventListener('mousedown', handleMouseDown);
    window.addEventListener('mouseup', handleMouseUp);
    window.addEventListener('mousemove', handleMouseMove);

    return () => {
      window.removeEventListener('keydown', handleKeyDown);
      window.removeEventListener('keyup', handleKeyUp);
      window.removeEventListener('mousedown', handleMouseDown);
      window.removeEventListener('mouseup', handleMouseUp);
      window.removeEventListener('mousemove', handleMouseMove);
    };
  }, [rotation, onRotationChange, onToggleFullBody, onRunChange, onBackwardChange, onLeftTurn, onRightTurn, onJump]);

  const lastRotUpdate = useRef(0);
  // 缓存Vector3对象，避免每帧创建
  const tempForward = useRef(new Vector3(0, 0, 1));
  const tempRight = useRef(new Vector3(1, 0, 0));
  const tempMoveVec = useRef(new Vector3());
  const tempCurrentPos = useRef(new Vector3());
  const tempDesiredPos = useRef(new Vector3());
  const tempSmoothed = useRef(new Euler(0, 0, 0, 'YXZ'));

  useFrame((state) => {
    // 平滑跟随目标旋转
    const yaw = yawRef.current + (targetYawRef.current - yawRef.current) * rotationSmooth;
    const pitch = pitchRef.current + (targetPitchRef.current - pitchRef.current) * rotationSmooth;
    yawRef.current = yaw;
    pitchRef.current = pitch;

    // 重用Euler对象
    tempSmoothed.current.set(pitch, yaw, 0);
    const now = state.clock.getElapsedTime();
    if (
      Math.abs(tempSmoothed.current.x - rotation.x) > 1e-4 ||
      Math.abs(tempSmoothed.current.y - rotation.y) > 1e-4 ||
      Math.abs(tempSmoothed.current.z - rotation.z) > 1e-4
    ) {
      if (now - lastRotUpdate.current > 1 / 60) { // ~60fps节流，提高响应速度
        onRotationChange(tempSmoothed.current.clone());
        lastRotUpdate.current = now;
      }
    }

    // 重用Vector3对象
    tempCurrentPos.current.copy(position);
    tempCurrentPos.current.y = 0;
    tempDesiredPos.current.copy(position);
    tempDesiredPos.current.y = 0;

    tempForward.current.set(0, 0, 1);
    tempRight.current.set(1, 0, 0);

    // 根据当前旋转计算移动方向
    tempForward.current.applyEuler(tempSmoothed.current);
    tempRight.current.applyEuler(tempSmoothed.current);
    tempForward.current.y = 0; // 保持水平移动
    tempRight.current.y = 0;
    tempForward.current.normalize();
    tempRight.current.normalize();

    tempMoveVec.current.set(0, 0, 0);
    if (keys.current.w) tempMoveVec.current.add(tempForward.current);
    if (keys.current.s) tempMoveVec.current.addScaledVector(tempForward.current, -1);
    if (keys.current.a) tempMoveVec.current.add(tempRight.current); // 左移
    if (keys.current.d) tempMoveVec.current.addScaledVector(tempRight.current, -1); // 右移

    // 检测移动状态并通知父组件（节流更新）
    const isMoving = tempMoveVec.current.lengthSq() > 0;
    if (onMovementChange && isMoving !== keys.current._lastMovingState) {
      onMovementChange(isMoving);
      keys.current._lastMovingState = isMoving;
    }

    if (isMoving) {
      const speed = baseMoveSpeed * (keys.current.shift ? runMultiplier : 1);
      tempMoveVec.current.normalize().multiplyScalar(speed);
      // 轴向分离移动，优先X再Z，避免卡角
      // 尝试沿X
      const nextX = tempDesiredPos.current.x + tempMoveVec.current.x;
      const zFixed = tempDesiredPos.current.z;
      const collidesX = walls.some(w =>
        nextX + playerRadius > w.minX &&
        nextX - playerRadius < w.maxX &&
        zFixed + playerRadius > w.minZ &&
        zFixed - playerRadius < w.maxZ
      );
      if (!collidesX) {
        tempDesiredPos.current.x = nextX;
      }

      // 尝试沿Z
      const nextZ = tempDesiredPos.current.z + tempMoveVec.current.z;
      const xFixed = tempDesiredPos.current.x;
      const collidesZ = walls.some(w =>
        xFixed + playerRadius > w.minX &&
        xFixed - playerRadius < w.maxX &&
        nextZ + playerRadius > w.minZ &&
        nextZ - playerRadius < w.maxZ
      );
      if (!collidesZ) {
        tempDesiredPos.current.z = nextZ;
      }

      // 展厅整体边界限制 - 扩大范围以允许在迷宫外部移动
      const bounds = 25; // 扩大边界，允许在迷宫外部移动
      tempDesiredPos.current.x = Math.max(-bounds + playerRadius, Math.min(bounds - playerRadius, tempDesiredPos.current.x));
      tempDesiredPos.current.z = Math.max(-bounds + playerRadius, Math.min(bounds - playerRadius, tempDesiredPos.current.z));
    }

    tempDesiredPos.current.y = 0;
    if (tempDesiredPos.current.distanceToSquared(tempCurrentPos.current) > 1e-6) {
      onPositionChange(tempDesiredPos.current.clone());
    }

  });

  // 此组件不处理提示逻辑


  return null;
};

// 展品组件
// 展品组件已移除

// 展览馆场景组件
const ExhibitionHall: React.FC<{
  exitPoint?: { x: number; z: number } | null;
  entranceDoor?: { x: number; z: number } | null;
  corridorEntrance?: { x: number; z: number } | null;
  corridorArtworks?: CorridorArtwork[];
  onSpeak?: (text: string) => void;
}> = ({ exitPoint, entranceDoor, corridorEntrance, corridorArtworks = [], onSpeak }) => {
  console.log('ExhibitionHall 组件渲染开始');
  console.log('exitPoint:', exitPoint);
  console.log('entranceDoor:', entranceDoor);
  console.log('corridorArtworks:', corridorArtworks);

  const DOOR_CENTER = { x: 0, z: -19.6 };
  const DOOR_SIZE = { x: 3.2 } as { x: number };
  return (
    <>
      {/* 未来科技感环境光照 */}
      <hemisphereLight args={[0xf0f9ff, 0x1e40af, 0.8]} />
      <directionalLight position={[10, 15, 8]} intensity={1.2} castShadow shadow-mapSize-width={1024} shadow-mapSize-height={1024} color={0x3b82f6} />

      {/* 大理石地板 - 白色大理石配蓝色发光图案 */}
      <Box position={[0, -0.5, 0]} args={[40, 1, 40]} receiveShadow>
        <meshStandardMaterial
          color="#f1f5f9"
          roughness={0.2}
          metalness={0.0}
          normalScale={[0.8, 0.8]}
        />
      </Box>

      {/* 大理石地板蓝色发光图案 - 蜿蜒流动的光带 */}
      {[-15, -10, -5, 0, 5, 10, 15].map((x, i) => (
        <Box key={`floor-light-x-${i}`} position={[x, -0.49, 0]} args={[0.2, 0.01, 35]} receiveShadow={false}>
          <meshStandardMaterial
            color="#3b82f6"
            emissive="#3b82f6"
            emissiveIntensity={2.0}
            roughness={0.0}
            metalness={0.0}
          />
        </Box>
      ))}
      {[-15, -10, -5, 0, 5, 10, 15].map((z, i) => (
        <Box key={`floor-light-z-${i}`} position={[0, -0.49, z]} args={[35, 0.01, 0.2]} receiveShadow={false}>
          <meshStandardMaterial
            color="#3b82f6"
            emissive="#3b82f6"
            emissiveIntensity={2.0}
            roughness={0.0}
            metalness={0.0}
          />
        </Box>
      ))}

      {/* 大理石地板蓝色点阵图案 */}
      {[-15, -10, -5, 0, 5, 10, 15].map((x) =>
        [-15, -10, -5, 0, 5, 10, 15].map((z) => (
          <Box key={`floor-dot-${x}-${z}`} position={[x, -0.48, z]} args={[0.3, 0.01, 0.3]} receiveShadow={false}>
            <meshStandardMaterial
              color="#3b82f6"
              emissive="#3b82f6"
              emissiveIntensity={1.5}
              roughness={0.0}
              metalness={0.0}
            />
          </Box>
        ))
      )}

      {/* 未来科技感天花板 - 深蓝色 */}
      <Box position={[0, 6, 0]} args={[40, 0.3, 40]} castShadow receiveShadow>
        <meshStandardMaterial color="#1e40af" roughness={0.02} metalness={0.0} />
      </Box>

      {/* 天花板蓝色点状光源 - 密密麻麻分布 */}
      {[-18, -15, -12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 18].map((x) =>
        [-18, -15, -12, -9, -6, -3, 0, 3, 6, 9, 12, 15, 18].map((z) => (
          <Box key={`ceiling-dot-${x}-${z}`} position={[x, 6.15, z]} args={[0.1, 0.05, 0.1]} receiveShadow={false}>
            <meshStandardMaterial
              color="#3b82f6"
              emissive="#3b82f6"
              emissiveIntensity={2.0}
              roughness={0.0}
              metalness={0.0}
            />
          </Box>
        ))
      )}

      {/* 天花板无人机状灯具 - 四旋翼设计 */}
      {[-15, -10, -5, 0, 5, 10, 15].map((x) =>
        [-15, -10, -5, 0, 5, 10, 15].map((z) => (
          <group key={`drone-light-${x}-${z}`} position={[x, 5.8, z]}>
            {/* 无人机主体 */}
            <mesh castShadow receiveShadow>
              <boxGeometry args={[0.4, 0.15, 0.4]} />
              <meshStandardMaterial
                color="#ffffff"
                roughness={0.1}
                metalness={0.8}
              />
            </mesh>
            {/* 四旋翼 */}
            {[
              [-0.25, 0, -0.25], [0.25, 0, -0.25],
              [-0.25, 0, 0.25], [0.25, 0, 0.25]
            ].map((pos, i) => (
              <mesh key={`rotor-${i}`} position={pos as [number, number, number]} castShadow receiveShadow>
                <boxGeometry args={[0.15, 0.03, 0.15]} />
                <meshStandardMaterial
                  color="#c0c0c0"
                  roughness={0.1}
                  metalness={0.8}
                />
              </mesh>
            ))}
            {/* 蓝色发光点 */}
            <mesh>
              <sphereGeometry args={[0.08, 8, 8]} />
              <meshStandardMaterial
                color="#3b82f6"
                emissive="#3b82f6"
                emissiveIntensity={2.0}
                roughness={0.0}
                metalness={0.0}
              />
            </mesh>
            {/* 蓝色照明效果 */}
            <pointLight position={[0, -0.15, 0]} color="#3b82f6" intensity={1.5} distance={3} />
          </group>
        ))
      )}


      {/* 外墙面（纯白墙） */}
      {/* 未来科技感墙壁 - 白色光滑表面 */}
      {/* 前墙 */}
      <Box position={[0, 3, -20]} args={[40, 6, 0.8]} castShadow receiveShadow>
        <meshStandardMaterial color="#ffffff" roughness={0.02} metalness={0.0} normalScale={[0.1, 0.1]} />
      </Box>

      {/* 现代科技门 */}
      <group position={[DOOR_CENTER.x, 0, DOOR_CENTER.z]}>
        {/* 门框 */}
        <Box position={[0, 2.2, 0.05]} args={[DOOR_SIZE.x + 0.2, 4.4, 0.1]} castShadow receiveShadow>
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.1} />
        </Box>
        {/* 门板 */}
        <Box position={[0, 2.2, 0.06]} args={[DOOR_SIZE.x, 4.4, 0.08]} castShadow receiveShadow>
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.1} />
        </Box>
        {/* 门把手 */}
        <Box position={[1.2, 2.2, 0.1]} args={[0.1, 0.3, 0.05]} castShadow receiveShadow>
          <meshStandardMaterial color="#3b82f6" roughness={0.2} metalness={0.8} />
        </Box>
        {/* 门把手LED */}
        <Box position={[1.2, 2.2, 0.12]} args={[0.05, 0.2, 0.01]} receiveShadow={false}>
          <meshStandardMaterial color="#3b82f6" emissive="#3b82f6" emissiveIntensity={0.8} />
        </Box>
        {/* 门边缘LED灯带 */}
        <Box position={[0, 0.1, 0.1]} args={[DOOR_SIZE.x, 0.02, 0.01]} receiveShadow={false}>
          <meshStandardMaterial color="#3b82f6" emissive="#3b82f6" emissiveIntensity={1.0} />
        </Box>
        <Box position={[0, 4.3, 0.1]} args={[DOOR_SIZE.x, 0.02, 0.01]} receiveShadow={false}>
          <meshStandardMaterial color="#3b82f6" emissive="#3b82f6" emissiveIntensity={1.0} />
        </Box>
        <Box position={[-1.5, 2.2, 0.1]} args={[0.02, 4.2, 0.01]} receiveShadow={false}>
          <meshStandardMaterial color="#3b82f6" emissive="#3b82f6" emissiveIntensity={1.0} />
        </Box>
        <Box position={[1.5, 2.2, 0.1]} args={[0.02, 4.2, 0.01]} receiveShadow={false}>
          <meshStandardMaterial color="#3b82f6" emissive="#3b82f6" emissiveIntensity={1.0} />
        </Box>
      </group>

      {/* 后墙 */}
      <Box position={[0, 3, 20]} args={[40, 6, 0.8]} castShadow receiveShadow>
        <meshStandardMaterial color="#ffffff" roughness={0.02} metalness={0.0} normalScale={[0.1, 0.1]} />
      </Box>

      {/* 左墙 */}
      <Box position={[-20, 3, 0]} args={[0.8, 6, 40]} castShadow receiveShadow>
        <meshStandardMaterial color="#ffffff" roughness={0.02} metalness={0.0} normalScale={[0.1, 0.1]} />
      </Box>

      {/* 右墙 */}
      <Box position={[20, 3, 0]} args={[0.8, 6, 40]} castShadow receiveShadow>
        <meshStandardMaterial color="#ffffff" roughness={0.02} metalness={0.0} normalScale={[0.1, 0.1]} />
      </Box>

      {/* 墙壁顶部蓝色霓虹灯带 */}
      {/* 前墙霓虹灯带 */}
      <Box position={[0, 5.95, -19.6]} args={[40, 0.05, 0.05]} receiveShadow={false}>
        <meshStandardMaterial
          color="#3b82f6"
          emissive="#3b82f6"
          emissiveIntensity={2.0}
          roughness={0.0}
          metalness={0.0}
        />
      </Box>
      {/* 后墙霓虹灯带 */}
      <Box position={[0, 5.95, 19.6]} args={[40, 0.05, 0.05]} receiveShadow={false}>
        <meshStandardMaterial
          color="#3b82f6"
          emissive="#3b82f6"
          emissiveIntensity={2.0}
          roughness={0.0}
          metalness={0.0}
        />
      </Box>
      {/* 左墙霓虹灯带 */}
      <Box position={[-19.6, 5.95, 0]} args={[0.05, 0.05, 40]} receiveShadow={false}>
        <meshStandardMaterial
          color="#3b82f6"
          emissive="#3b82f6"
          emissiveIntensity={2.0}
          roughness={0.0}
          metalness={0.0}
        />
      </Box>
      {/* 右墙霓虹灯带 */}
      <Box position={[19.6, 5.95, 0]} args={[0.05, 0.05, 40]} receiveShadow={false}>
        <meshStandardMaterial
          color="#3b82f6"
          emissive="#3b82f6"
          emissiveIntensity={2.0}
          roughness={0.0}
          metalness={0.0}
        />
      </Box>

      {/* 悬挂式八边形显示柜 - 未来科技感 */}
      {/* 左侧显示柜 */}
      {[-12, -6, 0, 6, 12].map((z, i) => (
        <group key={`display-left-${i}`} position={[-15, 4, z]}>
          {/* 八边形框架 */}
          <mesh castShadow receiveShadow>
            <cylinderGeometry args={[1.5, 1.5, 0.1, 8]} />
            <meshStandardMaterial
              color="#c0c0c0"
              roughness={0.1}
              metalness={0.8}
              normalScale={[0.1, 0.1]}
            />
          </mesh>
          {/* 蓝色霓虹灯边框 */}
          <mesh>
            <cylinderGeometry args={[1.6, 1.6, 0.05, 8]} />
            <meshStandardMaterial
              color="#3b82f6"
              emissive="#3b82f6"
              emissiveIntensity={2.0}
              roughness={0.0}
              metalness={0.0}
            />
          </mesh>
          {/* 透明玻璃面板 */}
          <mesh>
            <cylinderGeometry args={[1.4, 1.4, 0.02, 8]} />
            <meshStandardMaterial
              color="#ffffff"
              transparent={true}
              opacity={0.1}
              roughness={0.01}
              metalness={0.0}
            />
          </mesh>
          {/* 蓝色全息显示内容 */}
          <mesh>
            <cylinderGeometry args={[1.2, 1.2, 0.01, 8]} />
            <meshStandardMaterial
              color="#3b82f6"
              emissive="#3b82f6"
              emissiveIntensity={1.5}
              roughness={0.0}
              metalness={0.0}
            />
          </mesh>
        </group>
      ))}

      {/* 右侧显示柜 */}
      {[-12, -6, 0, 6, 12].map((z, i) => (
        <group key={`display-right-${i}`} position={[15, 4, z]}>
          {/* 八边形框架 */}
          <mesh castShadow receiveShadow>
            <cylinderGeometry args={[1.5, 1.5, 0.1, 8]} />
            <meshStandardMaterial
              color="#c0c0c0"
              roughness={0.1}
              metalness={0.8}
              normalScale={[0.1, 0.1]}
            />
          </mesh>
          {/* 蓝色霓虹灯边框 */}
          <mesh>
            <cylinderGeometry args={[1.6, 1.6, 0.05, 8]} />
            <meshStandardMaterial
              color="#3b82f6"
              emissive="#3b82f6"
              emissiveIntensity={2.0}
              roughness={0.0}
              metalness={0.0}
            />
          </mesh>
          {/* 透明玻璃面板 */}
          <mesh>
            <cylinderGeometry args={[1.4, 1.4, 0.02, 8]} />
            <meshStandardMaterial
              color="#ffffff"
              transparent={true}
              opacity={0.1}
              roughness={0.01}
              metalness={0.0}
            />
          </mesh>
          {/* 蓝色全息显示内容 */}
          <mesh>
            <cylinderGeometry args={[1.2, 1.2, 0.01, 8]} />
            <meshStandardMaterial
              color="#3b82f6"
              emissive="#3b82f6"
              emissiveIntensity={1.5}
              roughness={0.0}
              metalness={0.0}
            />
          </mesh>
        </group>
      ))}

      {/* 中央圆形平台 - 未来科技感 */}
      <group position={[0, 0.1, 0]}>
        {/* 圆形平台底座 */}
        <mesh position={[0, 0, 0]} castShadow receiveShadow>
          <cylinderGeometry args={[3, 3, 0.2, 16]} />
          <meshStandardMaterial
            color="#c0c0c0"
            roughness={0.1}
            metalness={0.8}
            normalScale={[0.1, 0.1]}
          />
        </mesh>
        {/* 蓝色发光边框 */}
        <mesh position={[0, 0.1, 0]} receiveShadow={false}>
          <cylinderGeometry args={[3.2, 3.2, 0.05, 16]} />
          <meshStandardMaterial
            color="#3b82f6"
            emissive="#3b82f6"
            emissiveIntensity={2.0}
            roughness={0.0}
            metalness={0.0}
          />
        </mesh>
        {/* 中央发光底座 */}
        <mesh position={[0, 0.15, 0]} receiveShadow={false}>
          <cylinderGeometry args={[1.5, 1.5, 0.1, 16]} />
          <meshStandardMaterial
            color="#3b82f6"
            emissive="#3b82f6"
            emissiveIntensity={3.0}
            roughness={0.0}
            metalness={0.0}
          />
        </mesh>
        {/* 中央发光效果 */}
        <pointLight position={[0, 0.2, 0]} color="#3b82f6" intensity={2.0} distance={5} />
      </group>

      {/* 现代会议室布局 - 基于图片设计 */}

      {/* 长会议桌 - 浅色木材配黑色中央条带 */}
      <group position={[0, 0, -9.5]}>
        {/* 会议桌主体 - 浅色木材 */}
        <Box position={[0, 0.4, 0]} args={[8, 0.8, 1.5]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5deb3" roughness={0.2} metalness={0.0} />
        </Box>
        {/* 中央黑色条带 - 电源和数据端口 */}
        <Box position={[0, 0.8, 0]} args={[8, 0.1, 0.3]} castShadow receiveShadow>
          <meshStandardMaterial color="#1a1a1a" roughness={0.1} metalness={0.8} />
        </Box>
        {/* 桌腿 - 银色金属 */}
        <Box position={[-3.5, 0.2, -0.6]} args={[0.2, 0.4, 0.2]} castShadow receiveShadow>
          <meshStandardMaterial color="#c0c0c0" roughness={0.1} metalness={0.9} />
        </Box>
        <Box position={[3.5, 0.2, -0.6]} args={[0.2, 0.4, 0.2]} castShadow receiveShadow>
          <meshStandardMaterial color="#c0c0c0" roughness={0.1} metalness={0.9} />
        </Box>
        <Box position={[-3.5, 0.2, 0.6]} args={[0.2, 0.4, 0.2]} castShadow receiveShadow>
          <meshStandardMaterial color="#c0c0c0" roughness={0.1} metalness={0.9} />
        </Box>
        <Box position={[3.5, 0.2, 0.6]} args={[0.2, 0.4, 0.2]} castShadow receiveShadow>
          <meshStandardMaterial color="#c0c0c0" roughness={0.1} metalness={0.9} />
        </Box>
      </group>

      {/* 会议椅 - 黑色网面配银色底座 */}
      {/* 左侧椅子 */}
      {[-3, -2, -1, 0, 1, 2, 3].map((x, i) => (
        <group key={`chair-left-${i}`} position={[x, 0, -11.5]}>
          {/* 椅子底座 - 银色悬臂式 */}
          <Box position={[0, 0.3, 0]} args={[0.1, 0.6, 0.1]} castShadow receiveShadow>
            <meshStandardMaterial color="#c0c0c0" roughness={0.1} metalness={0.9} />
          </Box>
          {/* 椅子座垫 - 黑色 */}
          <Box position={[0, 0.5, 0]} args={[0.6, 0.1, 0.6]} castShadow receiveShadow>
            <meshStandardMaterial color="#1a1a1a" roughness={0.3} metalness={0.0} />
          </Box>
          {/* 椅子靠背 - 黑色网面 */}
          <Box position={[0, 0.8, -0.2]} args={[0.6, 0.6, 0.1]} castShadow receiveShadow>
            <meshStandardMaterial color="#1a1a1a" roughness={0.3} metalness={0.0} />
          </Box>
        </group>
      ))}

      {/* 右侧椅子 */}
      {[-3, -2, -1, 0, 1, 2, 3].map((x, i) => (
        <group key={`chair-right-${i}`} position={[x, 0, -7.5]}>
          {/* 椅子底座 - 银色悬臂式 */}
          <Box position={[0, 0.3, 0]} args={[0.1, 0.6, 0.1]} castShadow receiveShadow>
            <meshStandardMaterial color="#c0c0c0" roughness={0.1} metalness={0.9} />
          </Box>
          {/* 椅子座垫 - 黑色 */}
          <Box position={[0, 0.5, 0]} args={[0.6, 0.1, 0.6]} castShadow receiveShadow>
            <meshStandardMaterial color="#1a1a1a" roughness={0.3} metalness={0.0} />
          </Box>
          {/* 椅子靠背 - 黑色网面 */}
          <Box position={[0, 0.8, 0.2]} args={[0.6, 0.6, 0.1]} castShadow receiveShadow>
            <meshStandardMaterial color="#1a1a1a" roughness={0.3} metalness={0.0} />
          </Box>
        </group>
      ))}


      {/* 桌面装饰 - 紫色花朵 */}
      {[-2, 0, 2].map((x, i) => (
        <group key={`flower-${i}`} position={[x, 0.9, -9.5]}>
          {/* 花瓶 - 黑色圆柱 */}
          <Box position={[0, 0.2, 0]} args={[0.2, 0.4, 0.2]} castShadow receiveShadow>
            <meshStandardMaterial color="#1a1a1a" roughness={0.1} metalness={0.8} />
          </Box>
          {/* 花朵 - 紫色 */}
          <Box position={[0, 0.6, 0]} args={[0.1, 0.3, 0.1]} castShadow receiveShadow>
            <meshStandardMaterial color="#9370db" roughness={0.0} metalness={0.0} />
          </Box>
        </group>
      ))}

      {/* 桌面物品 - 红色和橙色文件夹 */}
      {[-3, -2, -1, 0, 1, 2, 3].map((x, i) => (
        <Box key={`folder-${i}`} position={[x, 0.9, -10]} args={[0.3, 0.05, 0.4]} castShadow receiveShadow>
          <meshStandardMaterial
            color={i % 2 === 0 ? "#8b0000" : "#ff8c00"}
            roughness={0.3}
            metalness={0.0}
          />
        </Box>
      ))}

      {/* 绿色植物 - 窗边 */}
      <group position={[8, 0, 3]}>
        {/* 花盆 */}
        <Box position={[0, 0.3, 0]} args={[0.6, 0.6, 0.6]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5deb3" roughness={0.3} metalness={0.0} />
        </Box>
        {/* 植物 */}
        <Box position={[0, 0.8, 0]} args={[0.8, 1.6, 0.8]} castShadow receiveShadow>
          <meshStandardMaterial color="#228b22" roughness={0.3} metalness={0.0} />
        </Box>
      </group>

      {/* 中央圆形平台外围的墙壁 - 除前墙方向外 */}
      {/* 左墙 - 面向右墙的墙壁，延长创造更大空间 */}
      <Box position={[-9, 3, 0]} args={[0.2, 6, 26]} castShadow receiveShadow>
        <meshStandardMaterial color="#ffffff" roughness={0.02} metalness={0.0} normalScale={[0.1, 0.1]} />
      </Box>
      {/* 右墙 - 面向左墙的墙壁，延长创造更大空间 */}
      <Box position={[9, 3, 0]} args={[0.2, 6, 26]} castShadow receiveShadow>
        <meshStandardMaterial color="#ffffff" roughness={0.02} metalness={0.0} normalScale={[0.1, 0.1]} />
      </Box>
      {/* 后墙 - 长度延伸连接左右墙壁，创造更宽阔空间 */}
      <Box position={[0, 3, 7]} args={[18, 6, 0.2]} castShadow receiveShadow>
        <meshStandardMaterial color="#ffffff" roughness={0.02} metalness={0.0} normalScale={[0.1, 0.1]} />
      </Box>
      {/* 墙壁顶部蓝色霓虹灯带 */}
      {/* 左墙霓虹灯带 */}
      <Box position={[-8.9, 5.95, 0]} args={[0.05, 0.05, 26]} receiveShadow={false}>
        <meshStandardMaterial
          color="#3b82f6"
          emissive="#3b82f6"
          emissiveIntensity={2.0}
          roughness={0.0}
          metalness={0.0}
        />
      </Box>
      {/* 右墙霓虹灯带 */}
      <Box position={[8.9, 5.95, 0]} args={[0.05, 0.05, 26]} receiveShadow={false}>
        <meshStandardMaterial
          color="#3b82f6"
          emissive="#3b82f6"
          emissiveIntensity={2.0}
          roughness={0.0}
          metalness={0.0}
        />
      </Box>
      {/* 后墙霓虹灯带 */}
      <Box position={[0, 5.95, 6.9]} args={[18, 0.05, 0.05]} receiveShadow={false}>
        <meshStandardMaterial
          color="#3b82f6"
          emissive="#3b82f6"
          emissiveIntensity={2.0}
          roughness={0.0}
          metalness={0.0}
        />
      </Box>

      {/* 悬浮矩形棱镜 - 全息显示 */}
      <group position={[0, 2.5, 0]}>
        {/* 矩形棱镜主体 - 深钢蓝色，厚度减半 */}
        <Box args={[4, 2.5, 0.4]} position={[0, 0, 0]} castShadow receiveShadow>
          <meshStandardMaterial color="#4682b4" transparent opacity={0.7} roughness={0.1} metalness={0.0} />
        </Box>
        {/* 发光边框 - 深钢蓝色发光效果 */}
        <Box args={[4.1, 2.6, 0.05]} position={[0, 0, 0.2]} receiveShadow={false}>
          <meshStandardMaterial color="#4682b4" emissive="#4682b4" emissiveIntensity={1.8} />
        </Box>
        <Box args={[4.1, 2.6, 0.05]} position={[0, 0, -0.2]} receiveShadow={false}>
          <meshStandardMaterial color="#4682b4" emissive="#4682b4" emissiveIntensity={1.8} />
        </Box>
        <Box args={[0.05, 2.6, 0.4]} position={[2.05, 0, 0]} receiveShadow={false}>
          <meshStandardMaterial color="#4682b4" emissive="#4682b4" emissiveIntensity={1.8} />
        </Box>
        <Box args={[0.05, 2.6, 0.4]} position={[-2.05, 0, 0]} receiveShadow={false}>
          <meshStandardMaterial color="#4682b4" emissive="#4682b4" emissiveIntensity={1.8} />
        </Box>
        {/* 内部全息内容 - 深钢蓝色 */}
        <Box args={[3.5, 0.1, 0.3]} position={[0, 0.5, 0]} receiveShadow={false}>
          <meshStandardMaterial color="#4682b4" emissive="#4682b4" emissiveIntensity={1.2} />
        </Box>
        <Box args={[3.5, 0.1, 0.3]} position={[0, -0.5, 0]} receiveShadow={false}>
          <meshStandardMaterial color="#4682b4" emissive="#4682b4" emissiveIntensity={1.2} />
        </Box>
        <Box args={[0.1, 2.0, 0.3]} position={[1.2, 0, 0]} receiveShadow={false}>
          <meshStandardMaterial color="#4682b4" emissive="#4682b4" emissiveIntensity={1.2} />
        </Box>
        <Box args={[0.1, 2.0, 0.3]} position={[-1.2, 0, 0]} receiveShadow={false}>
          <meshStandardMaterial color="#4682b4" emissive="#4682b4" emissiveIntensity={1.2} />
        </Box>
      </group>


      {/* 现代简约床 - 按照图片设计 - 大房间背后区域 */}
      <group position={[-4.0, 0, 9.5]} rotation={[0, 0, 0]}>
        {/* 床架 - 浅灰色矩形框架 */}
        <Box position={[0, 0.15, 0]} args={[3.6, 0.3, 3.2]} castShadow receiveShadow>
          <meshStandardMaterial color="#d3d3d3" roughness={0.3} metalness={0.0} />
        </Box>

        {/* 床头板 - 粉色/淡紫色主部分 */}
        <Box position={[0, 1.2, -1.6]} args={[3.6, 1.2, 0.1]} castShadow receiveShadow>
          <meshStandardMaterial color="#d8bfd8" roughness={0.2} metalness={0.0} />
        </Box>

        {/* 床头板底座 - 白色矩形部分 */}
        <Box position={[0, 0.6, -1.61]} args={[3.6, 0.4, 0.1]} castShadow receiveShadow>
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.0} />
        </Box>

        {/* 床垫 - 白色厚床垫 */}
        <Box position={[0, 0.4, 0.01]} args={[3.4, 0.2, 3.0]} castShadow receiveShadow>
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.0} />
        </Box>

        {/* 被子 - 浅灰色被子覆盖下半部分 */}
        <Box position={[0, 0.5, 0.52]} args={[3.4, 0.1, 1.2]} castShadow receiveShadow>
          <meshStandardMaterial color="#d3d3d3" roughness={0.2} metalness={0.0} />
        </Box>

        {/* 枕头 - 淡绿色枕头 */}
        <Box position={[0, 0.6, -1.11]} args={[2.8, 0.2, 1.0]} castShadow receiveShadow>
          <meshStandardMaterial color="#90ee90" roughness={0.1} metalness={0.0} />
        </Box>

        {/* 装饰条 - 淡绿色水平装饰条 */}
        <Box position={[0, 0.55, 0.22]} args={[3.4, 0.05, 0.1]} receiveShadow={false}>
          <meshStandardMaterial color="#98fb98" roughness={0.0} metalness={0.0} />
        </Box>
      </group>

      {/* 现代简约木制桌子 - 床边配套 */}
      <group position={[-4.0, 0, 12.5]} rotation={[0, 0, 0]}>
        {/* 桌面 - 浅色木制 */}
        <Box position={[0, 0.5, 0]} args={[2.0, 0.08, 1.2]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5deb3" roughness={0.2} metalness={0.0} />
        </Box>

        {/* 桌边 - 木制边框 */}
        <Box position={[0, 0.46, 0]} args={[2.0, 0.08, 1.2]} castShadow receiveShadow>
          <meshStandardMaterial color="#deb887" roughness={0.1} metalness={0.0} />
        </Box>

        {/* 桌面装饰条 - 金色装饰 */}
        <Box position={[0, 0.54, 0]} args={[1.8, 0.02, 1.0]} receiveShadow={false}>
          <meshStandardMaterial color="#ffd700" roughness={0.0} metalness={0.8} />
        </Box>

        {/* 桌腿1 - 左前腿 */}
        <Box position={[-0.8, 0.25, -0.5]} args={[0.08, 0.5, 0.08]} castShadow receiveShadow>
          <meshStandardMaterial color="#deb887" roughness={0.1} metalness={0.0} />
        </Box>

        {/* 桌腿2 - 右前腿 */}
        <Box position={[0.8, 0.25, -0.5]} args={[0.08, 0.5, 0.08]} castShadow receiveShadow>
          <meshStandardMaterial color="#deb887" roughness={0.1} metalness={0.0} />
        </Box>

        {/* 桌腿3 - 左后腿 */}
        <Box position={[-0.8, 0.25, 0.5]} args={[0.08, 0.5, 0.08]} castShadow receiveShadow>
          <meshStandardMaterial color="#deb887" roughness={0.1} metalness={0.0} />
        </Box>

        {/* 桌腿4 - 右后腿 */}
        <Box position={[0.8, 0.25, 0.5]} args={[0.08, 0.5, 0.08]} castShadow receiveShadow>
          <meshStandardMaterial color="#deb887" roughness={0.1} metalness={0.0} />
        </Box>

        {/* 桌腿装饰 - 金色环 */}
        {[-0.8, 0.8].map((x, i) => (
          <Box key={`leg-ring-${i}`} position={[x, 0.1, -0.5]} args={[0.12, 0.02, 0.12]} receiveShadow={false}>
            <meshStandardMaterial color="#ffd700" roughness={0.0} metalness={0.8} />
          </Box>
        ))}
        {[-0.8, 0.8].map((x, i) => (
          <Box key={`leg-ring-back-${i}`} position={[x, 0.1, 0.5]} args={[0.12, 0.02, 0.12]} receiveShadow={false}>
            <meshStandardMaterial color="#ffd700" roughness={0.0} metalness={0.8} />
          </Box>
        ))}

        {/* 桌面装饰 - 中央装饰 */}
        <Box position={[0, 0.55, 0]} args={[0.4, 0.02, 0.2]} receiveShadow={false}>
          <meshStandardMaterial color="#ffd700" roughness={0.0} metalness={0.8} />
        </Box>
      </group>

      {/* 灰色抽屉柜 - 复刻版 - 桌椅旁边 */}
      <group position={[5.5, 0, 8.5]} rotation={[0, -Math.PI / 2, 0]}>
        {/* 柜体主体 - 灰色 */}
        <Box position={[0, 0.6, 0]} args={[1.2, 1.2, 0.4]} castShadow receiveShadow>
          <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
        </Box>

        {/* 顶部表面 - 略微突出 */}
        <Box position={[0, 1.2, 0]} args={[1.3, 0.05, 0.45]} castShadow receiveShadow>
          <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
        </Box>

        {/* 四个短腿 */}
        {[
          [-0.5, 0.1, -0.15], [0.5, 0.1, -0.15],
          [-0.5, 0.1, 0.15], [0.5, 0.1, 0.15]
        ].map((pos, i) => (
          <Box key={`cabinet-leg-${i}`} position={pos as [number, number, number]} args={[0.08, 0.2, 0.08]} castShadow receiveShadow>
            <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
          </Box>
        ))}

        {/* 顶部两个小抽屉 - 并排 */}
        {/* 左小抽屉 */}
        <Box position={[-0.3, 0.9, 0.21]} args={[0.5, 0.15, 0.02]} castShadow receiveShadow>
          <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
        </Box>
        {/* 左小抽屉把手 */}
        <Box position={[-0.3, 0.9, 0.22]} args={[0.06, 0.06, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#000000" roughness={0.1} metalness={0.8} />
        </Box>

        {/* 右小抽屉 */}
        <Box position={[0.3, 0.9, 0.21]} args={[0.5, 0.15, 0.02]} castShadow receiveShadow>
          <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
        </Box>
        {/* 右小抽屉把手 */}
        <Box position={[0.3, 0.9, 0.22]} args={[0.06, 0.06, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#000000" roughness={0.1} metalness={0.8} />
        </Box>

        {/* 下方两个大抽屉 - 垂直排列 */}
        {/* 上大抽屉 */}
        <Box position={[0, 0.6, 0.21]} args={[1.0, 0.2, 0.02]} castShadow receiveShadow>
          <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
        </Box>
        {/* 上大抽屉把手 */}
        <Box position={[0, 0.6, 0.22]} args={[0.06, 0.06, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#000000" roughness={0.1} metalness={0.8} />
        </Box>

        {/* 下大抽屉 */}
        <Box position={[0, 0.3, 0.21]} args={[1.0, 0.2, 0.02]} castShadow receiveShadow>
          <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
        </Box>
        {/* 下大抽屉把手 */}
        <Box position={[0, 0.3, 0.22]} args={[0.06, 0.06, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#000000" roughness={0.1} metalness={0.8} />
        </Box>

        {/* 抽屉面板装饰 - 轻微凹陷效果 */}
        {/* 小抽屉面板 */}
        <Box position={[-0.3, 0.9, 0.20]} args={[0.45, 0.12, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#707070" roughness={0.3} metalness={0.0} />
        </Box>
        <Box position={[0.3, 0.9, 0.20]} args={[0.45, 0.12, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#707070" roughness={0.3} metalness={0.0} />
        </Box>

        {/* 大抽屉面板 */}
        <Box position={[0, 0.6, 0.20]} args={[0.9, 0.17, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#707070" roughness={0.3} metalness={0.0} />
        </Box>
        <Box position={[0, 0.3, 0.20]} args={[0.9, 0.17, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#707070" roughness={0.3} metalness={0.0} />
        </Box>
      </group>

      {/* 现代桌椅组合 - 按照图片设计 - 屏风旁边 - 加长版 */}
      <group position={[4.0, 0, 9.5]} rotation={[0, 0, 0]}>
        {/* 桌子主体 - 现代简约风格 - 加长 */}
        <Box position={[0, 0.5, 0]} args={[2.0, 1.0, 1.0]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5f5f5" roughness={0.1} metalness={0.0} />
        </Box>

        {/* 桌子桌面 - 加长 */}
        <Box position={[0, 1.0, 0]} args={[2.2, 0.08, 1.2]} castShadow receiveShadow>
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.0} />
        </Box>

        {/* 桌子腿 - 现代细腿设计 - 加长 */}
        {[
          [-0.9, 0.25, -0.4], [0.9, 0.25, -0.4],
          [-0.9, 0.25, 0.4], [0.9, 0.25, 0.4]
        ].map((pos, i) => (
          <Box key={`table-leg-${i}`} position={pos as [number, number, number]} args={[0.05, 0.5, 0.05]} castShadow receiveShadow>
            <meshStandardMaterial color="#e0e0e0" roughness={0.2} metalness={0.1} />
          </Box>
        ))}

        {/* 椅子 - 现代简约设计 - 放大 */}
        <group position={[0, 0, -1.2]}>
          {/* 椅子座面 - 放大 */}
          <Box position={[0, 0.5, 0]} args={[0.8, 0.08, 0.8]} castShadow receiveShadow>
            <meshStandardMaterial color="#f5f5f5" roughness={0.1} metalness={0.0} />
          </Box>

          {/* 椅子靠背 - 放大 */}
          <Box position={[0, 0.9, -0.3]} args={[0.8, 0.8, 0.08]} castShadow receiveShadow>
            <meshStandardMaterial color="#f5f5f5" roughness={0.1} metalness={0.0} />
          </Box>

          {/* 椅子腿 - 放大 */}
          {[
            [-0.3, 0.25, -0.3], [0.3, 0.25, -0.3],
            [-0.3, 0.25, 0.3], [0.3, 0.25, 0.3]
          ].map((pos, i) => (
            <Box key={`chair-leg-${i}`} position={pos as [number, number, number]} args={[0.05, 0.5, 0.05]} castShadow receiveShadow>
              <meshStandardMaterial color="#e0e0e0" roughness={0.2} metalness={0.1} />
            </Box>
          ))}
        </group>

        {/* 装饰物品 - 桌面上 - 放大 */}
        {/* 笔记本电脑 - 放大 */}
        <Box position={[0.3, 1.08, 0.2]} args={[0.5, 0.03, 0.35]} castShadow receiveShadow>
          <meshStandardMaterial color="#2c2c2c" roughness={0.1} metalness={0.8} />
        </Box>

        {/* 咖啡杯 - 放大 */}
        <mesh position={[-0.3, 1.08, 0.2]} castShadow receiveShadow>
          <cylinderGeometry args={[0.06, 0.06, 0.12, 16]} />
          <meshStandardMaterial color="#8B4513" roughness={0.3} metalness={0.0} />
        </mesh>

        {/* 书本 - 放大 */}
        <Box position={[0, 1.08, -0.3]} args={[0.25, 0.03, 0.35]} castShadow receiveShadow>
          <meshStandardMaterial color="#4a90e2" roughness={0.3} metalness={0.0} />
        </Box>

        {/* 台灯 - 新增装饰 */}
        <group position={[0.6, 1.08, 0.4]}>
          <Box position={[0, 0.3, 0]} args={[0.05, 0.6, 0.05]} castShadow receiveShadow>
            <meshStandardMaterial color="#e0e0e0" roughness={0.2} metalness={0.1} />
          </Box>
          <mesh position={[0, 0.6, 0]} castShadow receiveShadow>
            <sphereGeometry args={[0.08, 16, 16]} />
            <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.0} emissive="#ffffff" emissiveIntensity={0.3} />
          </mesh>
        </group>
      </group>

      {/* 四面板屏风 - 按照图片设计 - 床旁边 */}
      <group position={[1.0, 0, 9.5]} rotation={[0, Math.PI / 2, 0]}>
        {/* 整体屏风框架 - 浅色木材 */}
        <Box position={[0, 1.5, 0]} args={[3.2, 3.0, 0.1]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5deb3" roughness={0.2} metalness={0.0} />
        </Box>

        {/* 四个白色面板区域 */}
        {/* 面板1 - 左侧 */}
        <Box position={[-1.2, 1.5, 0.05]} args={[0.6, 2.8, 0.02]} castShadow receiveShadow>
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.0} />
        </Box>
        {/* 面板1波浪形镂空 - 上部分 */}
        <Box position={[-1.2, 2.2, 0.06]} args={[0.4, 0.3, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5deb3" roughness={0.2} metalness={0.0} />
        </Box>
        {/* 面板1波浪形镂空 - 下部分 */}
        <Box position={[-1.2, 0.8, 0.06]} args={[0.4, 0.3, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5deb3" roughness={0.2} metalness={0.0} />
        </Box>

        {/* 面板2 - 左中 */}
        <Box position={[-0.4, 1.5, 0.05]} args={[0.6, 2.8, 0.02]} castShadow receiveShadow>
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.0} />
        </Box>
        {/* 面板2波浪形镂空 - 长条形 */}
        <Box position={[-0.4, 1.5, 0.06]} args={[0.3, 1.5, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5deb3" roughness={0.2} metalness={0.0} />
        </Box>

        {/* 面板3 - 右中 */}
        <Box position={[0.4, 1.5, 0.05]} args={[0.6, 2.8, 0.02]} castShadow receiveShadow>
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.0} />
        </Box>
        {/* 面板3波浪形镂空 - 长条形 */}
        <Box position={[0.4, 1.5, 0.06]} args={[0.3, 1.5, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5deb3" roughness={0.2} metalness={0.0} />
        </Box>

        {/* 面板4 - 右侧 */}
        <Box position={[1.2, 1.5, 0.05]} args={[0.6, 2.8, 0.02]} castShadow receiveShadow>
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.0} />
        </Box>
        {/* 面板4波浪形镂空 - 上部分 */}
        <Box position={[1.2, 2.2, 0.06]} args={[0.4, 0.3, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5deb3" roughness={0.2} metalness={0.0} />
        </Box>
        {/* 面板4波浪形镂空 - 下部分 */}
        <Box position={[1.2, 0.8, 0.06]} args={[0.4, 0.3, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5deb3" roughness={0.2} metalness={0.0} />
        </Box>

        {/* 面板分隔线 */}
        {[-0.8, 0, 0.8].map((x, i) => (
          <Box key={`divider-${i}`} position={[x, 1.5, 0.04]} args={[0.02, 3.0, 0.02]} castShadow receiveShadow>
            <meshStandardMaterial color="#f5deb3" roughness={0.2} metalness={0.0} />
          </Box>
        ))}

        {/* 顶部和底部横梁 */}
        <Box position={[0, 3.0, 0]} args={[3.2, 0.08, 0.1]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5deb3" roughness={0.2} metalness={0.0} />
        </Box>
        <Box position={[0, 0, 0]} args={[3.2, 0.08, 0.1]} castShadow receiveShadow>
          <meshStandardMaterial color="#f5deb3" roughness={0.2} metalness={0.0} />
        </Box>
      </group>

      {/* 灰色抽屉柜 - 按照图片设计 - 贴着床房间左墙 */}
      <group position={[-8.5, 0, 9.5]} rotation={[0, Math.PI / 2, 0]}>
        {/* 柜体主体 - 灰色 */}
        <Box position={[0, 0.6, 0]} args={[1.2, 1.2, 0.4]} castShadow receiveShadow>
          <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
        </Box>

        {/* 顶部表面 - 略微突出 */}
        <Box position={[0, 1.2, 0]} args={[1.3, 0.05, 0.45]} castShadow receiveShadow>
          <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
        </Box>

        {/* 四个短腿 */}
        {[
          [-0.5, 0.1, -0.15], [0.5, 0.1, -0.15],
          [-0.5, 0.1, 0.15], [0.5, 0.1, 0.15]
        ].map((pos, i) => (
          <Box key={`cabinet-leg-${i}`} position={pos as [number, number, number]} args={[0.08, 0.2, 0.08]} castShadow receiveShadow>
            <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
          </Box>
        ))}

        {/* 顶部两个小抽屉 - 并排 */}
        {/* 左小抽屉 */}
        <Box position={[-0.3, 0.9, 0.21]} args={[0.5, 0.15, 0.02]} castShadow receiveShadow>
          <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
        </Box>
        {/* 左小抽屉把手 */}
        <Box position={[-0.3, 0.9, 0.22]} args={[0.06, 0.06, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#000000" roughness={0.1} metalness={0.8} />
        </Box>

        {/* 右小抽屉 */}
        <Box position={[0.3, 0.9, 0.21]} args={[0.5, 0.15, 0.02]} castShadow receiveShadow>
          <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
        </Box>
        {/* 右小抽屉把手 */}
        <Box position={[0.3, 0.9, 0.22]} args={[0.06, 0.06, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#000000" roughness={0.1} metalness={0.8} />
        </Box>

        {/* 下方两个大抽屉 - 垂直排列 */}
        {/* 上大抽屉 */}
        <Box position={[0, 0.6, 0.21]} args={[1.0, 0.2, 0.02]} castShadow receiveShadow>
          <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
        </Box>
        {/* 上大抽屉把手 */}
        <Box position={[0, 0.6, 0.22]} args={[0.06, 0.06, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#000000" roughness={0.1} metalness={0.8} />
        </Box>

        {/* 下大抽屉 */}
        <Box position={[0, 0.3, 0.21]} args={[1.0, 0.2, 0.02]} castShadow receiveShadow>
          <meshStandardMaterial color="#808080" roughness={0.3} metalness={0.0} />
        </Box>
        {/* 下大抽屉把手 */}
        <Box position={[0, 0.3, 0.22]} args={[0.06, 0.06, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#000000" roughness={0.1} metalness={0.8} />
        </Box>

        {/* 抽屉面板装饰 - 轻微凹陷效果 */}
        {/* 小抽屉面板 */}
        <Box position={[-0.3, 0.9, 0.20]} args={[0.45, 0.12, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#707070" roughness={0.3} metalness={0.0} />
        </Box>
        <Box position={[0.3, 0.9, 0.20]} args={[0.45, 0.12, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#707070" roughness={0.3} metalness={0.0} />
        </Box>

        {/* 大抽屉面板 */}
        <Box position={[0, 0.6, 0.20]} args={[0.9, 0.17, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#707070" roughness={0.3} metalness={0.0} />
        </Box>
        <Box position={[0, 0.3, 0.20]} args={[0.9, 0.17, 0.01]} castShadow receiveShadow>
          <meshStandardMaterial color="#707070" roughness={0.3} metalness={0.0} />
        </Box>
      </group>
      <group position={[-6, 0, 0]}>
        {/* 圆柱主体 */}
        <mesh position={[0, 3, 0]} castShadow receiveShadow>
          <cylinderGeometry args={[0.8, 0.8, 6, 16]} />
          <meshStandardMaterial color="#ffffff" transparent opacity={0.2} roughness={0.1} metalness={0.1} />
        </mesh>
        {/* 内部发光渐变 */}
        <mesh position={[0, 3, 0]} receiveShadow={false}>
          <cylinderGeometry args={[0.7, 0.7, 6, 16]} />
          <meshStandardMaterial color="#3b82f6" emissive="#3b82f6" emissiveIntensity={0.8} />
        </mesh>
        {/* 顶部发光环 */}
        <mesh position={[0, 6.1, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow={false}>
          <torusGeometry args={[0.9, 0.05, 8, 16]} />
          <meshStandardMaterial color="#06b6d4" emissive="#06b6d4" emissiveIntensity={1.0} />
        </mesh>
        {/* 底部发光环 */}
        <mesh position={[0, 0.1, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow={false}>
          <torusGeometry args={[0.9, 0.05, 8, 16]} />
          <meshStandardMaterial color="#06b6d4" emissive="#06b6d4" emissiveIntensity={1.0} />
        </mesh>
      </group>


      {/* 科技感墙面装饰 - 几何面板 */}
      {/* 前墙几何装饰 - 避开门的位置 */}
      {[-15, -10, -5, 5, 10, 15].map((x, i) => (
        <group key={`front-panel-${i}`} position={[x, 3, -19.5]}>
          <Box args={[2, 3, 0.1]} castShadow receiveShadow>
            <meshStandardMaterial color="#f8fafc" roughness={0.1} metalness={0.1} />
          </Box>
          <Box args={[1.8, 2.8, 0.05]} position={[0, 0, 0.05]} castShadow receiveShadow>
            <meshStandardMaterial color="#3b82f6" roughness={0.2} metalness={0.8} />
          </Box>
        </group>
      ))}

      {/* 出口地面标识 */}
      {!!exitPoint && (
        <>
          {/* 绿色点光，营造发光效果 */}
          <pointLight position={[exitPoint.x, 1.1, exitPoint.z]} color="#10b981" intensity={0.9} distance={3.5} />
          {/* 出口字样：立起来，始终面向玩家来向（Billboard） */}
          {/* 暂时注释掉Text组件以避免字体加载错误 */}
          {/* <Billboard position={[exitPoint.x, 0.6, exitPoint.z]} follow lockX={false} lockY={false} lockZ={false}>
            <Text
              position={[0, 0, 0]}
              rotation={[0, 0, 0]}
              fontSize={0.5}
              color="#10b981"
              outlineWidth={0.02}
              outlineColor="#065f46"
              anchorX="center"
              anchorY="middle"
            >
              出口
            </Text>
          </Billboard> */}
        </>
      )}

      {/* 内部入口标识已移除（保留变量以避免未使用警告） */}
      {!!entranceDoor && null}

      {/* 走廊处“入口”字样与提示光（外墙封闭后不再展示）*/}
      {!!corridorEntrance && (
        <>
          <pointLight position={[corridorEntrance.x, 1.0, corridorEntrance.z]} color="#f59e0b" intensity={0.9} distance={3.0} />
          {/* 暂时注释掉Text组件以避免字体加载错误 */}
          {/* <Billboard position={[corridorEntrance.x, 0.5, corridorEntrance.z]} follow>
            <Text fontSize={0.45} color="#f59e0b" anchorX="center" anchorY="middle">入口</Text>
          </Billboard> */}
        </>
      )}

      {/* 柱子装饰已移除 */}

      {/* 展品与中央展台已移除 */}

      {/* 现代展示桌 - 精致玻璃设计 */}
      <group position={[6, 0, -6]}>
        {/* 玻璃桌面 - 透明玻璃效果 */}
        <Box args={[2.0, 0.03, 1.2]} position={[0, 0.9, 0]} castShadow receiveShadow>
          <meshStandardMaterial color="#ffffff" transparent opacity={0.05} roughness={0.01} metalness={0.95} />
        </Box>

        {/* 黑色支撑柱 - 两个垂直支撑 */}
        <Box args={[0.15, 0.8, 0.15]} position={[-0.7, 0.5, 0]} castShadow receiveShadow>
          <meshStandardMaterial color="#1a1a1a" roughness={0.2} metalness={0.1} />
        </Box>
        <Box args={[0.15, 0.8, 0.15]} position={[0.7, 0.5, 0]} castShadow receiveShadow>
          <meshStandardMaterial color="#1a1a1a" roughness={0.2} metalness={0.1} />
        </Box>

        {/* 蓝色发光底座平台 */}
        <Box args={[1.8, 0.1, 1.0]} position={[0, 0.1, 0]} castShadow receiveShadow>
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.1} />
        </Box>
        {/* 蓝色发光层 */}
        <Box args={[1.8, 0.02, 1.0]} position={[0, 0.11, 0]} receiveShadow={false}>
          <meshStandardMaterial color="#3b82f6" emissive="#3b82f6" emissiveIntensity={1.2} />
        </Box>

        {/* 白色弧形底座 */}
        <mesh position={[0, 0.05, 0]} castShadow receiveShadow>
          <cylinderGeometry args={[1.0, 1.0, 0.1, 32]} />
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.05} />
        </mesh>

        {/* 桌面装饰 - 白色球形摆件 */}
        <mesh position={[-0.3, 0.95, 0.2]} castShadow receiveShadow>
          <sphereGeometry args={[0.08, 16, 16]} />
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.1} />
        </mesh>
        <mesh position={[0.3, 0.95, -0.2]} castShadow receiveShadow>
          <sphereGeometry args={[0.08, 16, 16]} />
          <meshStandardMaterial color="#ffffff" roughness={0.1} metalness={0.1} />
        </mesh>

        {/* 蓝色装饰环 - 桌面边缘 */}
        <mesh position={[0, 0.92, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow={false}>
          <torusGeometry args={[1.1, 0.02, 8, 32]} />
          <meshStandardMaterial color="#3b82f6" emissive="#3b82f6" emissiveIntensity={0.8} />
        </mesh>

        {/* 底座装饰环 */}
        <mesh position={[0, 0.15, 0]} rotation={[Math.PI / 2, 0, 0]} receiveShadow={false}>
          <torusGeometry args={[1.1, 0.03, 8, 32]} />
          <meshStandardMaterial color="#3b82f6" emissive="#3b82f6" emissiveIntensity={0.6} />
        </mesh>

        {/* 支撑柱装饰 - 蓝色发光条 */}
        <Box args={[0.02, 0.6, 0.02]} position={[-0.7, 0.5, 0]} receiveShadow={false}>
          <meshStandardMaterial color="#3b82f6" emissive="#3b82f6" emissiveIntensity={0.8} />
        </Box>
        <Box args={[0.02, 0.6, 0.02]} position={[0.7, 0.5, 0]} receiveShadow={false}>
          <meshStandardMaterial color="#3b82f6" emissive="#3b82f6" emissiveIntensity={0.8} />
        </Box>
      </group>

      {/* 独立小房间 - 现代简约风格 */}
      <group position={[-17, 0, -17]} rotation={[0, -Math.PI / 2, 0]}>
        {/* 小房间地面 - 精致大理石质感地面 */}
        <Box position={[0, -0.4, 0]} args={[8, 0.2, 6]} receiveShadow>
          <meshStandardMaterial
            color="#f8fafc"
            roughness={0.05}
            metalness={0.0}
            normalScale={[0.2, 0.2]}
          />
        </Box>

        {/* 地面装饰线条 - 金色边框 */}
        <Box position={[0, -0.39, 0]} args={[8.1, 0.01, 0.1]} receiveShadow={false}>
          <meshStandardMaterial
            color="#f59e0b"
            emissive="#f59e0b"
            emissiveIntensity={0.3}
            roughness={0.1}
            metalness={0.8}
          />
        </Box>
        <Box position={[0, -0.39, 0]} args={[0.1, 0.01, 6.1]} receiveShadow={false}>
          <meshStandardMaterial
            color="#f59e0b"
            emissive="#f59e0b"
            emissiveIntensity={0.3}
            roughness={0.1}
            metalness={0.8}
          />
        </Box>

        {/* 小房间墙壁 - 精致现代质感 - 高度与展览馆一致 - 宽度增加 */}
        {/* 前墙已移除 - 面对右墙的墙壁 */}
        {/* 后墙 */}
        <Box position={[0, 3, 3]} args={[8, 6, 0.1]} castShadow receiveShadow>
          <meshStandardMaterial
            color="#f1f5f9"
            roughness={0.1}
            metalness={0.0}
            normalScale={[0.3, 0.3]}
          />
        </Box>
        {/* 左墙已移除 - 开口朝向展览馆 */}
        {/* 右墙已移除 - 开口朝向展览馆 */}
        {/* 面向后墙的墙壁 - 再向后墙方向加厚0.1米 - 防止穿模 */}
        <Box position={[4.2, 3, 0]} args={[0.4, 6, 6]} castShadow receiveShadow>
          <meshStandardMaterial
            color="#f1f5f9"
            roughness={0.1}
            metalness={0.0}
            normalScale={[0.3, 0.3]}
          />
        </Box>

        {/* 小房间天花板已移除 - 吊灯将挂在展览馆天花板上 */}

        {/* 开放入口已移除 - 面向右墙的门窗已删除 */}

        {/* L形高级木制柜台 - 极浅胡桃木台面配极浅橡木底座 - 调整位置 - 旋转180度 */}
        <group position={[0, 0, 1]} rotation={[0, Math.PI, 0]}>
          {/* 柜台主体 - L形 - 极浅胡桃木台面 */}
          <Box args={[2.5, 0.9, 0.5]} position={[-0.3, 0.45, 0]} castShadow receiveShadow>
            <meshStandardMaterial
              color="#deb887"
              roughness={0.3}
              metalness={0.0}
              normalScale={[0.2, 0.2]}
            />
          </Box>
          <Box args={[0.5, 0.9, 1.2]} position={[-1.0, 0.45, 0.6]} castShadow receiveShadow>
            <meshStandardMaterial
              color="#deb887"
              roughness={0.3}
              metalness={0.0}
              normalScale={[0.2, 0.2]}
            />
          </Box>

          {/* 极浅橡木底座 - 垂直木板 */}
          {[-1.0, -0.6, -0.2, 0.2, 0.6, 1.0].map((x, i) => (
            <Box key={`counter-wood-${i}`} args={[0.1, 0.8, 0.4]} position={[x, 0.4, 0]} castShadow receiveShadow>
              <meshStandardMaterial
                color="#faf0e6"
                roughness={0.4}
                metalness={0.0}
                normalScale={[0.3, 0.3]}
              />
            </Box>
          ))}
          {/* L形部分的极浅橡木底座 */}
          {[0.2, 0.4, 0.6, 0.8, 1.0].map((z, i) => (
            <Box key={`counter-wood-l-${i}`} args={[0.1, 0.8, 0.1]} position={[-1.0, 0.4, z]} castShadow receiveShadow>
              <meshStandardMaterial
                color="#faf0e6"
                roughness={0.4}
                metalness={0.0}
                normalScale={[0.3, 0.3]}
              />
            </Box>
          ))}

          {/* 极浅金色木质装饰条 */}
          <Box args={[2.7, 0.05, 0.05]} position={[-0.3, 0.05, 0]} castShadow receiveShadow>
            <meshStandardMaterial
              color="#f0e68c"
              emissive="#f0e68c"
              emissiveIntensity={0.1}
              roughness={0.2}
              metalness={0.0}
            />
          </Box>
          <Box args={[0.05, 0.05, 1.3]} position={[-1.0, 0.05, 0.6]} castShadow receiveShadow>
            <meshStandardMaterial
              color="#f0e68c"
              emissive="#f0e68c"
              emissiveIntensity={0.1}
              roughness={0.2}
              metalness={0.0}
            />
          </Box>

          {/* 极浅胡桃木储物格 */}
          <Box args={[0.3, 0.25, 0.3]} position={[-1.0, 0.2, 0.2]} castShadow receiveShadow>
            <meshStandardMaterial
              color="#deb887"
              roughness={0.3}
              metalness={0.0}
              normalScale={[0.2, 0.2]}
            />
          </Box>
        </group>

        {/* 发光玻璃展示柜 - 精致现代设计 - 贴在左墙上 - 旋转180度 - 高度调整 - 宽度增加 */}
        {/* 左墙展示柜1 */}
        <group position={[3.9, 3, 1.5]} rotation={[0, Math.PI, 0]}>
          <Box args={[0.1, 3, 1.2]} castShadow receiveShadow>
            <meshStandardMaterial
              color="#1e293b"
              roughness={0.05}
              metalness={0.95}
              normalScale={[0.1, 0.1]}
            />
          </Box>
          <Box args={[0.05, 2.9, 1.1]} position={[0.05, 0, 0]} receiveShadow={false}>
            <meshStandardMaterial
              color="#ffffff"
              transparent
              opacity={0.02}
              roughness={0.01}
              metalness={0.98}
            />
          </Box>
          {[-0.8, -0.2, 0.4, 1.0].map((y, j) => (
            <Box key={`shelf-left-1-${j}`} args={[0.8, 0.02, 1.0]} position={[0.05, y, 0]} receiveShadow={false}>
              <meshStandardMaterial
                color="#ffffff"
                transparent
                opacity={0.1}
                roughness={0.01}
                metalness={0.98}
              />
            </Box>
          ))}
          <Box args={[0.02, 0.02, 1.0]} position={[0.05, 1.3, 0]} receiveShadow={false}>
            <meshStandardMaterial
              color="#3b82f6"
              emissive="#3b82f6"
              emissiveIntensity={2.0}
            />
          </Box>
        </group>

        {/* 左墙展示柜2 */}
        <group position={[3.9, 3, -1.5]} rotation={[0, Math.PI, 0]}>
          <Box args={[0.1, 3, 1.2]} castShadow receiveShadow>
            <meshStandardMaterial
              color="#1e293b"
              roughness={0.05}
              metalness={0.95}
              normalScale={[0.1, 0.1]}
            />
          </Box>
          <Box args={[0.05, 2.9, 1.1]} position={[0.05, 0, 0]} receiveShadow={false}>
            <meshStandardMaterial
              color="#ffffff"
              transparent
              opacity={0.02}
              roughness={0.01}
              metalness={0.98}
            />
          </Box>
          {[-0.8, -0.2, 0.4, 1.0].map((y, j) => (
            <Box key={`shelf-left-2-${j}`} args={[0.8, 0.02, 1.0]} position={[0.05, y, 0]} receiveShadow={false}>
              <meshStandardMaterial
                color="#ffffff"
                transparent
                opacity={0.1}
                roughness={0.01}
                metalness={0.98}
              />
            </Box>
          ))}
          <Box args={[0.02, 0.02, 1.0]} position={[0.05, 1.3, 0]} receiveShadow={false}>
            <meshStandardMaterial
              color="#3b82f6"
              emissive="#3b82f6"
              emissiveIntensity={2.0}
            />
          </Box>
        </group>

        {/* 几何吊灯群 - 7个精致多边形吊灯 - 挂在展览馆天花板上 - 高度与展览馆一致 */}
        {[
          { pos: [-1.5, 5.5, -1.5], height: 0.8 },
          { pos: [-0.5, 5.2, -1.5], height: 1.1 },
          { pos: [0.5, 5.5, -1.5], height: 0.8 },
          { pos: [1.5, 5.2, -1.5], height: 1.0 },
          { pos: [-1.0, 5.3, 0], height: 0.9 },
          { pos: [0, 5.1, 0], height: 1.2 },
          { pos: [1.0, 5.3, 0], height: 0.9 }
        ].map(({ pos, height }, i) => (
          <group key={`pendant-light-${i}`} position={pos as [number, number, number]}>
            {/* 吊灯线 - 从展览馆天花板垂下 - 高度调整 */}
            <Box args={[0.01, height + 0.5, 0.01]} position={[0, -height / 2 - 0.25, 0]} receiveShadow={false}>
              <meshStandardMaterial
                color="#1e293b"
                roughness={0.05}
                metalness={0.95}
                normalScale={[0.1, 0.1]}
              />
            </Box>
            {/* 多边形金属框架 - 精致设计 */}
            <mesh position={[0, -height, 0]} castShadow receiveShadow>
              <cylinderGeometry args={[0.25, 0.25, 0.12, 8]} />
              <meshStandardMaterial
                color="#1e293b"
                roughness={0.05}
                metalness={0.95}
                normalScale={[0.1, 0.1]}
              />
            </mesh>
            {/* 精致灯泡 - 蓝色发光 */}
            <mesh position={[0, -height, 0]} receiveShadow={false}>
              <sphereGeometry args={[0.15, 16, 16]} />
              <meshStandardMaterial
                color="#3b82f6"
                emissive="#3b82f6"
                emissiveIntensity={1.5}
                roughness={0.05}
                metalness={0.0}
              />
            </mesh>
            {/* 精致发光效果 */}
            <pointLight position={[0, -height, 0]} color="#3b82f6" intensity={1.5} distance={4} />
          </group>
        ))}

        {/* 小房间内部照明 */}
        <pointLight position={[0, 3.5, 0]} color="#ffffff" intensity={0.3} distance={6} />

        {/* 精致装饰元素 - 左墙已移除 */}
        {/* 墙面装饰线条 - 金色 - 仅保留后墙装饰 */}
        <Box position={[0, 4.5, 2.95]} args={[8, 0.02, 0.02]} receiveShadow={false}>
          <meshStandardMaterial
            color="#f59e0b"
            emissive="#f59e0b"
            emissiveIntensity={0.4}
            roughness={0.1}
            metalness={0.8}
          />
        </Box>

        {/* 地面装饰图案 - 几何图形 */}
        <Box position={[1, -0.38, 1]} args={[0.5, 0.01, 0.5]} receiveShadow={false}>
          <meshStandardMaterial
            color="#3b82f6"
            emissive="#3b82f6"
            emissiveIntensity={0.2}
            roughness={0.1}
            metalness={0.8}
          />
        </Box>
        <Box position={[-1, -0.38, -1]} args={[0.5, 0.01, 0.5]} receiveShadow={false}>
          <meshStandardMaterial
            color="#3b82f6"
            emissive="#3b82f6"
            emissiveIntensity={0.2}
            roughness={0.1}
            metalness={0.8}
          />
        </Box>

        {/* 精致植物装饰 */}
        <group position={[2, 0, 2]}>
          <Box args={[0.1, 0.8, 0.1]} position={[0, 0.4, 0]} castShadow receiveShadow>
            <meshStandardMaterial color="#22c55e" roughness={0.3} metalness={0.0} />
          </Box>
          <Box args={[0.3, 0.3, 0.3]} position={[0, 0.8, 0]} castShadow receiveShadow>
            <meshStandardMaterial color="#16a34a" roughness={0.4} metalness={0.0} />
          </Box>
        </group>

        <group position={[-2, 0, -2]}>
          <Box args={[0.1, 0.8, 0.1]} position={[0, 0.4, 0]} castShadow receiveShadow>
            <meshStandardMaterial color="#22c55e" roughness={0.3} metalness={0.0} />
          </Box>
          <Box args={[0.3, 0.3, 0.3]} position={[0, 0.8, 0]} castShadow receiveShadow>
            <meshStandardMaterial color="#16a34a" roughness={0.4} metalness={0.0} />
          </Box>
        </group>
      </group>

      {/* 迷宫墙壁展品装饰 - 仅保留外围走廊内侧墙面展品（自动从 src/img 加载） */}
      {corridorArtworks.map((a, i) => (
        <Artwork key={`art-${i}`} position={a.position} rotation={a.rotation} imageUrl={a.url} title={a.title} description="" size={0.8} onSpeak={onSpeak} />
      ))}

    </>
  );
};

// 数字人模型（与主角位置一致）
const AvatarFollower: React.FC<{
  cameraPosition: Vector3;
  cameraRotation: Euler;
  modelUrl?: string;
  isMoving?: boolean; // 添加移动状态参数
  isRunning?: boolean;
  isBackward?: boolean;
  leftTurnTick?: number;
  rightTurnTick?: number;
  jumpTick?: number;
  isJumping?: boolean;
  isOnGround?: boolean; // 添加地面检测状态
  onJumpFinished?: () => void;
}> = ({ cameraPosition, cameraRotation, modelUrl, isMoving = false, isRunning = false, isBackward = false, leftTurnTick = 0, rightTurnTick = 0, jumpTick = 0, isJumping = false, isOnGround = true, onJumpFinished }) => {
  // 加载模型（简化版本，不使用复杂动画）
  const url = modelUrl ?? AVATAR_URL;
  console.log('AvatarFollower 开始加载模型:', url);

  const gltf = useGLTF(url) as GLTF;
  console.log('AvatarFollower 模型加载成功:', gltf);
  // 加载行走/奔跑/后退/左转/待机FBX
  const walkingFbx = useFBX('/animations/Walking.fbx');
  const runningFbx = useFBX('/animations/Treadmill Running.fbx');
  // 使用 URL 编码的路径，避免空格导致的资源加载问题
  const backwardFbx = useFBX('/animations/Walking%20Backward.fbx');
  const backRunningFbx = useFBX('/animations/Running%20Backward.fbx');
  const leftTurnFbx = useFBX('/animations/Left%20Turn.fbx');
  const rightTurnFbx = useFBX('/animations/Right%20Turn.fbx');
  const jumpFbx = useFBX('/animations/Jump.fbx');
  const idleFbx = useFBX('/animations/Standing%20W_Briefcase%20Idle.fbx');
  const animationsRef = useRef<{ idle?: THREE.AnimationAction; walk?: THREE.AnimationAction; run?: THREE.AnimationAction; back?: THREE.AnimationAction; backRun?: THREE.AnimationAction; leftTurn?: THREE.AnimationAction; rightTurn?: THREE.AnimationAction; jump?: THREE.AnimationAction } | null>(null);
  const mixerRef = useRef<THREE.AnimationMixer | null>(null);
  const groupRef = useRef<Group>(null!);
  const headMeshRefs = useRef<THREE.Mesh[]>([]);
  const protectedUpperMeshesRef = useRef<THREE.Mesh[]>([]);

  // 模型位置就是主角位置（cameraPosition 变量现代表主角位置）
  const avatarPosition = cameraPosition;

  // 初始化动画
  useEffect(() => {
    if (!gltf?.scene) return;
    mixerRef.current = new THREE.AnimationMixer(gltf.scene);
    const mixer = mixerRef.current;

    // 极保守的面部过滤，只过滤最明确有问题的轨道
    const problematicFacePattern = /(Wolf3D_Head|Wolf3D_)/i;
    const visibilityPattern = /\.visible$/i;
    const materialPattern = /\.material/i;
    const filterFaceTracks = (clip?: THREE.AnimationClip) => {
      if (!clip) return undefined;
      const cloned = clip.clone();
      // 只过滤最明确有问题的轨道，保留所有头部、颈部、面部相关轨道
      const originalTrackCount = cloned.tracks.length;
      cloned.tracks = cloned.tracks.filter(t => {
        const name = t.name || '';
        // 去除面部问题轨道；禁止任何可见性/材质被动画修改，避免衣服被隐藏
        if (problematicFacePattern.test(name)) return false;
        if (visibilityPattern.test(name)) return false;
        if (materialPattern.test(name)) return false;
        return true;
      });
      const filteredTrackCount = cloned.tracks.length;
      console.log(`Filtered ${originalTrackCount - filteredTrackCount} tracks (face/visibility/material), kept ${filteredTrackCount}`);
      return cloned;
    };

    // 将FBX动画重定向到GLB骨架（安全回退）
    const hasSkinnedMesh = (root?: THREE.Object3D) => {
      if (!root) return false;
      let found = false;
      root.traverse((o) => {
        const mesh = o as unknown as { isSkinnedMesh?: boolean; skeleton?: { bones?: unknown[] } };
        if (mesh.isSkinnedMesh && mesh.skeleton && Array.isArray(mesh.skeleton.bones)) {
          found = true;
        }
      });
      return found;
    };

    const retargetClip = (clip?: THREE.AnimationClip, source?: THREE.Object3D) => {
      if (!clip || !source) return undefined;
      let mapped: THREE.AnimationClip | undefined;
      try {
        // 仅当存在 retargetClip 且 FBX 含骨骼时才尝试
        const maybe = SkeletonUtils as unknown as { retargetClip?: (target: THREE.Object3D, source: THREE.Object3D, clip: THREE.AnimationClip) => THREE.AnimationClip };
        if (maybe.retargetClip && hasSkinnedMesh(source)) {
          mapped = maybe.retargetClip(gltf.scene, source, clip);
          // 如果重定向失败或结果有问题，回退到原始动画
          if (!mapped || mapped.tracks.length === 0) {
            console.warn('Animation retargeting failed, using original clip');
            mapped = undefined;
          } else {
            console.log(`Successfully retargeted animation with ${mapped.tracks.length} tracks`);
          }
        }
      } catch (error) {
        console.warn('Animation retargeting error:', error);
        mapped = undefined;
      }
      // 应用面部过滤
      const filteredClip = filterFaceTracks(mapped ?? clip);
      // 如果过滤后没有轨道了，回退到原始动画
      if (!filteredClip || filteredClip.tracks.length === 0) {
        console.warn('All animation tracks filtered out, using original clip');
        return clip;
      }
      return filteredClip;
    };

    // Idle: 优先使用专门的待机动画FBX文件
    const rawIdle = idleFbx.animations?.[0] as unknown as THREE.AnimationClip | undefined;
    let idleClip: THREE.AnimationClip | null = null;
    if (rawIdle) {
      idleClip = retargetClip(rawIdle, idleFbx) ?? null;
    } else if (Array.isArray(gltf.animations) && gltf.animations.length > 0) {
      // 后备方案：使用GLB的第一条动画
      idleClip = gltf.animations[0];
    }

    const rawWalk = walkingFbx.animations?.[0] as unknown as THREE.AnimationClip | undefined;
    const rawRun = runningFbx.animations?.[0] as unknown as THREE.AnimationClip | undefined;

    const rawBack = backwardFbx.animations?.[0] as unknown as THREE.AnimationClip | undefined;
    const rawBackRun = backRunningFbx.animations?.[0] as unknown as THREE.AnimationClip | undefined;
    const rawLeftTurn = leftTurnFbx.animations?.[0] as unknown as THREE.AnimationClip | undefined;
    const rawRightTurn = rightTurnFbx.animations?.[0] as unknown as THREE.AnimationClip | undefined;
    const rawJump = jumpFbx.animations?.[0] as unknown as THREE.AnimationClip | undefined;
    const walkClip = retargetClip(rawWalk, walkingFbx);
    const runClip = retargetClip(rawRun, runningFbx);
    let backClip = retargetClip(rawBack, backwardFbx);
    let backRunClip = retargetClip(rawBackRun, backRunningFbx);
    const leftTurnClip = retargetClip(rawLeftTurn, leftTurnFbx);
    const rightTurnClip = retargetClip(rawRightTurn, rightTurnFbx);
    const jumpClip = retargetClip(rawJump, jumpFbx);
    // 后备：若未能加载到后退动画，则退回走路动画
    if (!backClip && walkClip) backClip = walkClip;
    // 后备：若未能加载到后退跑步，则退回前进跑步
    if (!backRunClip && runClip) backRunClip = runClip;

    const actions: { idle?: THREE.AnimationAction; walk?: THREE.AnimationAction; run?: THREE.AnimationAction; back?: THREE.AnimationAction; backRun?: THREE.AnimationAction; leftTurn?: THREE.AnimationAction; rightTurn?: THREE.AnimationAction; jump?: THREE.AnimationAction } = {};
    if (idleClip) actions.idle = mixer.clipAction(idleClip);
    if (walkClip) actions.walk = mixer.clipAction(walkClip);
    if (runClip) actions.run = mixer.clipAction(runClip);
    if (backClip) actions.back = mixer.clipAction(backClip);
    if (backRunClip) actions.backRun = mixer.clipAction(backRunClip);
    if (leftTurnClip) actions.leftTurn = mixer.clipAction(leftTurnClip);
    if (rightTurnClip) actions.rightTurn = mixer.clipAction(rightTurnClip);
    if (jumpClip) actions.jump = mixer.clipAction(jumpClip);
    animationsRef.current = actions;

    // 一次性缓存头部相关网格，避免每帧全场景遍历
    headMeshRefs.current = [];
    protectedUpperMeshesRef.current = [];
    const pushIfHead = (child: THREE.Object3D) => {
      if (child instanceof THREE.Mesh) {
        const name = (child.name || '').toLowerCase();
        if (name.includes('head') || name.includes('face') || name.includes('hair') || name.includes('wolf3d_head')) {
          headMeshRefs.current.push(child);
          child.visible = true;
          child.frustumCulled = false;
        }
        // 保护上半身/服装网格，避免被动画可见性轨道隐藏
        if (
          name.includes('upper') || name.includes('torso') || name.includes('spine') ||
          name.includes('chest') || name.includes('shirt') || name.includes('coat') ||
          name.includes('cloth') || name.includes('outfit') || name.includes('wolf3d')
        ) {
          protectedUpperMeshesRef.current.push(child);
          child.visible = true;
          child.frustumCulled = false;
        }
      }
    };
    gltf.scene.traverse(pushIfHead);

    // 初始播放idle或walk的停止帧 - 优化流畅性
    if (actions.idle) {
      actions.idle.reset().fadeIn(0.05).play(); // 快速淡入
    } else if (actions.walk) {
      actions.walk.reset().fadeIn(0.05).play(); // 快速淡入
    }

    return () => {
      mixer.stopAllAction();
      animationsRef.current = null;
      mixerRef.current = null;
    };
  }, [gltf, walkingFbx, runningFbx, backwardFbx, backRunningFbx, leftTurnFbx, rightTurnFbx, jumpFbx, idleFbx]);

  // 跳起动画处理：单独的useEffect，只在jumpTick变化时触发
  useEffect(() => {
    const mixer = mixerRef.current;
    const actions = animationsRef.current;
    if (!mixer || !actions || !actions.jump || jumpTick === 0 || !isJumping) return;

    // 边跑边跳：优化流畅性，快速切换
    // 只停止待机和走路动画，保留跑步相关动画
    [actions.idle, actions.walk, actions.leftTurn, actions.rightTurn].forEach(a => {
      if (a) a.fadeOut(0.05); // 更快的淡出
    });

    // 播放跳起动画（只播放一次）
    actions.jump.reset().setLoop(THREE.LoopOnce, 1).clampWhenFinished = true;
    actions.jump.enabled = true;
    actions.jump.fadeIn(0.1).play(); // 更快的淡入

    // 跳起动画结束后，根据当前状态恢复相应动画
    const jumpStartTime = Date.now();
    const jumpDuration = actions.jump.getClip().duration * 1000; // 转换为毫秒

    const checkJumpFinished = () => {
      if (actions.jump && Date.now() - jumpStartTime >= jumpDuration) {
        actions.jump.fadeOut(0.2);

        // 重置跳起状态
        if (onJumpFinished) {
          onJumpFinished();
        }

        // 根据当前状态恢复动画 - 边跑边跳优化，快速恢复
        if (isBackward && isRunning && actions.backRun) {
          // 后退跑步
          actions.backRun.enabled = true;
          actions.backRun.reset().fadeIn(0.1).play(); // 更快的恢复
        } else if (isBackward && actions.back) {
          // 后退走路
          actions.back.enabled = true;
          actions.back.reset().fadeIn(0.1).play(); // 更快的恢复
        } else if (isMoving && isRunning && actions.run) {
          // 前进跑步 - 边跑边跳的主要情况
          actions.run.enabled = true;
          actions.run.reset().fadeIn(0.1).play(); // 更快的恢复
        } else if (isMoving && actions.walk) {
          // 前进走路
          actions.walk.enabled = true;
          actions.walk.reset().fadeIn(0.1).play(); // 更快的恢复
        } else if (actions.idle) {
          // 待机状态
          actions.idle.enabled = true;
          actions.idle.reset().fadeIn(0.1).play(); // 更快的恢复
        }
        return true; // 表示检查完成
      }
      return false; // 表示还需要继续检查
    };

    // 将检查函数存储到ref中，在useFrame中调用
    jumpCheckRef.current = checkJumpFinished;
    mixer.update(0);
  }, [jumpTick, isJumping, isMoving, isRunning, isBackward, onJumpFinished]); // 添加isJumping依赖

  // 根据移动/奔跑/后退状态切换动画
  useEffect(() => {
    const mixer = mixerRef.current;
    const actions = animationsRef.current;
    if (!mixer || !actions) return;

    // 如果正在跳跃，不切换其他动画，让跳跃动画继续
    if (isJumping) return;

    // 优化动画流畅性：使用智能混合让动画切换更加流畅

    // 智能动画混合：让动画切换更加流畅
    const playSmoothTransition = (next?: THREE.AnimationAction) => {
      [actions.idle, actions.walk, actions.run, actions.back, actions.backRun].forEach(a => {
        if (!a) return;
        if (a === next) {
          // 目标动画：快速淡入
          a.enabled = true;
          if (!a.isRunning()) {
            a.reset().fadeIn(0.05).play();
          } else {
            a.setEffectiveWeight(1.0);
          }
        } else {
          // 其他动画：快速淡出
          if (a.isRunning()) {
            a.fadeOut(0.05);
          }
        }
      });
    };

    // 头部骨骼保护：确保头部骨骼在动画播放时保持可见
    const protectHeadBones = () => {
      if (!gltf?.scene) return;

      // 查找头部相关的骨骼和网格
      const headBones: THREE.Bone[] = [];
      const headMeshes: THREE.Mesh[] = [];

      gltf.scene.traverse((child) => {
        if (child instanceof THREE.Bone) {
          const name = child.name.toLowerCase();
          if (name.includes('head') || name.includes('neck') || name.includes('skull')) {
            headBones.push(child);
          }
        } else if (child instanceof THREE.Mesh) {
          const name = child.name.toLowerCase();
          if (name.includes('head') || name.includes('face') || name.includes('hair')) {
            headMeshes.push(child);
            // 确保头部网格可见
            child.visible = true;
          }
        }
      });

      // 确保头部骨骼和网格存在且可见
      if (headBones.length > 0) {
        console.log(`Found ${headBones.length} head/neck bones:`, headBones.map(b => b.name));
      }
      if (headMeshes.length > 0) {
        console.log(`Found ${headMeshes.length} head meshes:`, headMeshes.map(m => m.name));
      }

      if (headBones.length === 0 && headMeshes.length === 0) {
        console.warn('No head bones or meshes found in model');
      }
    };

    // 1) 一次性左转（按下 A 时触发）：优化流畅性
    if (leftTurnTick > 0 && actions.leftTurn) {
      // 不停止其他动画，让转向动画叠加播放
      actions.leftTurn.reset().setLoop(THREE.LoopOnce, 1).clampWhenFinished = true;
      actions.leftTurn.enabled = true;
      actions.leftTurn.fadeIn(0.05).play(); // 快速淡入
      mixer.update(0);
      // 不 return，让后续逻辑依旧根据移动状态决定
    }

    // 2) 一次性右转（按下 D 时触发）：优化流畅性
    if (rightTurnTick > 0 && actions.rightTurn) {
      // 不停止其他动画，让转向动画叠加播放
      actions.rightTurn.reset().setLoop(THREE.LoopOnce, 1).clampWhenFinished = true;
      actions.rightTurn.enabled = true;
      actions.rightTurn.fadeIn(0.05).play(); // 快速淡入
      mixer.update(0);
    }

    // 3) 优先后退奔跑（Shift+S），其次后退走路（S）
    if (isBackward && isRunning && actions.backRun) {
      // 若后退跑步与前进跑步是同动作，使用倒放
      if (actions.backRun === actions.run && actions.run) {
        actions.run.timeScale = -1;
      } else if (actions.run) {
        actions.run.timeScale = 1;
      }
      playSmoothTransition(actions.backRun);
      protectHeadBones();
      mixer.update(0);
      return;
    }

    if (isBackward && actions.back) {
      if (actions.walk) actions.walk.timeScale = 1; // 清理可能的倒放残留
      // 若后退动画与走路动画为同一动作（后备方案），用倒放实现
      if (actions.back === actions.walk && actions.walk) {
        actions.walk.timeScale = -1;
      }
      playSmoothTransition(actions.back);
      protectHeadBones();
      // 立即推进一帧，避免切换延迟导致"看不到动作开始"
      mixer.update(0);
      return;
    }

    // 未按 S，再根据是否移动决定
    if (!isMoving) {
      if (actions.idle) {
        playSmoothTransition(actions.idle);
        protectHeadBones(); // 保护头部骨骼
      } else if (actions.walk) {
        playSmoothTransition(undefined); // 退到静止（无动画）
        protectHeadBones(); // 保护头部骨骼
      }
      return;
    }

    // 恢复走路动画的 timeScale（避免从倒放残留）
    if (actions.walk) actions.walk.timeScale = 1;

    if (isRunning && isBackward && actions.backRun) {
      // 若后退跑步与前进跑步是同动作，使用倒放
      if (actions.backRun === actions.run && actions.run) {
        actions.run.timeScale = -1;
      }
      playSmoothTransition(actions.backRun);
      protectHeadBones();
      mixer.update(0);
    } else if (isRunning && actions.run) {
      playSmoothTransition(actions.run);
      protectHeadBones(); // 保护头部骨骼
      mixer.update(0);
    } else if (actions.walk) {
      playSmoothTransition(actions.walk);
      protectHeadBones(); // 保护头部骨骼
      mixer.update(0);
    }
  }, [isMoving, isRunning, isBackward, leftTurnTick, rightTurnTick, gltf.scene, isJumping]);

  // 调试：观察状态与动作是否齐全（可按需移除）
  useEffect(() => {
    const actions = animationsRef.current;
    if (!actions) return;
    console.log('[AvatarFollower] 状态', { isMoving, isRunning, isBackward, isJumping, isOnGround, hasBack: !!actions.back });
  }, [isMoving, isRunning, isBackward, isJumping, isOnGround]);

  // 跳起动画检查ref
  const jumpCheckRef = useRef<(() => boolean) | null>(null);

  // 优化动画更新频率，减少不必要的计算
  const lastMeshCheck = useRef(0);
  useFrame((_, delta) => {
    if (mixerRef.current) mixerRef.current.update(delta);

    // 检查跳起动画是否结束
    if (jumpCheckRef.current && jumpCheckRef.current()) {
      jumpCheckRef.current = null; // 清除检查函数
    }

    // 降低网格可见性检查频率，从每帧改为每10帧检查一次
    const now = performance.now();
    if (now - lastMeshCheck.current > 100) { // 每100ms检查一次
      // 轻量保证：对缓存的头部网格强制可见，避免动画切换导致可见性异常
      for (const mesh of headMeshRefs.current) {
        if (!mesh.visible) mesh.visible = true;
        if (mesh.frustumCulled) mesh.frustumCulled = false;
      }
      // 同样保护上半身/服装网格
      for (const mesh of protectedUpperMeshesRef.current) {
        if (!mesh.visible) mesh.visible = true;
        if (mesh.frustumCulled) mesh.frustumCulled = false;
      }
      lastMeshCheck.current = now;
    }
  });

  console.log('AvatarFollower 渲染模型，位置:', avatarPosition);

  return (
    <group ref={groupRef} position={avatarPosition} rotation={[0, cameraRotation.y, 0]}>
      {gltf && gltf.scene ? (
        <primitive
          object={gltf.scene}
          scale={0.9}
          // 确保模型位置稳定，不受动画影响
          position={[0, 0, 0]}
        />
      ) : (
        // 显示简单的3D人物占位符
        <>
          {/* 头部 */}
          <mesh position={[0, 1.7, 0]}>
            <sphereGeometry args={[0.3, 16, 16]} />
            <meshStandardMaterial color="#ffdbac" />
          </mesh>

          {/* 身体 */}
          <mesh position={[0, 1.2, 0]}>
            <boxGeometry args={[0.6, 0.8, 0.3]} />
            <meshStandardMaterial color="#4a90e2" />
          </mesh>

          {/* 手臂 */}
          <mesh position={[-0.4, 1.2, 0]}>
            <boxGeometry args={[0.2, 0.6, 0.2]} />
            <meshStandardMaterial color="#ffdbac" />
          </mesh>
          <mesh position={[0.4, 1.2, 0]}>
            <boxGeometry args={[0.2, 0.6, 0.2]} />
            <meshStandardMaterial color="#ffdbac" />
          </mesh>

          {/* 腿部 */}
          <mesh position={[-0.15, 0.4, 0]}>
            <boxGeometry args={[0.2, 0.8, 0.2]} />
            <meshStandardMaterial color="#2c3e50" />
          </mesh>
          <mesh position={[0.15, 0.4, 0]}>
            <boxGeometry args={[0.2, 0.8, 0.2]} />
            <meshStandardMaterial color="#2c3e50" />
          </mesh>
        </>
      )}
    </group>
  );
};

// 相机跟随与防遮挡
const CameraRig: React.FC<{
  targetPosition: Vector3;
  targetRotation: Euler;
  fullBody?: boolean;
  walls: WallAABB[];
}> = ({ targetPosition, targetRotation, fullBody = true, walls }) => {
  const { camera } = useThree();
  const smoothedPos = useRef(new Vector3());
  const initialized = useRef(false);

  // 线段与AABB相交测试（slab 方法），返回是否相交以及最近t
  const segmentHitsAABB = (p0: Vector3, p1: Vector3, box: WallAABB): number | null => {
    const dir = p1.clone().sub(p0);
    const inv = new Vector3(
      dir.x !== 0 ? 1 / dir.x : Infinity,
      dir.y !== 0 ? 1 / dir.y : Infinity,
      dir.z !== 0 ? 1 / dir.z : Infinity
    );
    let tmin = 0;
    let tmax = 1;
    const min = new Vector3(box.minX, -10, box.minZ);
    const max = new Vector3(box.maxX, 10, box.maxZ);
    for (const axis of ['x', 'y', 'z'] as const) {
      const t1 = ((min as unknown as Record<'x' | 'y' | 'z', number>)[axis] - (p0 as unknown as Record<'x' | 'y' | 'z', number>)[axis]) * (inv as unknown as Record<'x' | 'y' | 'z', number>)[axis];
      const t2 = ((max as unknown as Record<'x' | 'y' | 'z', number>)[axis] - (p0 as unknown as Record<'x' | 'y' | 'z', number>)[axis]) * (inv as unknown as Record<'x' | 'y' | 'z', number>)[axis];
      const tNear = Math.min(t1, t2);
      const tFar = Math.max(t1, t2);
      tmin = Math.max(tmin, tNear);
      tmax = Math.min(tmax, tFar);
      if (tmin > tmax) return null;
    }
    return tmin >= 0 && tmin <= 1 ? tmin : null;
  };

  // 缓存Vector3对象，避免每帧创建
  const tempBackOffset = useRef(new Vector3());
  const tempRot = useRef(new Euler(0, 0, 0, 'YXZ'));
  const tempDesired = useRef(new Vector3());
  const tempHead = useRef(new Vector3());
  const tempSafeDesired = useRef(new Vector3());
  const lastObstructionT = useRef<number | null>(null);

  // 相机抖动抑制
  const lastCameraPos = useRef(new Vector3());
  const cameraVelocity = useRef(new Vector3());
  const maxCameraVelocity = 0.3; // 降低最大相机移动速度，增加平滑度

  useFrame((_, delta) => {
    const distance = fullBody ? AVATAR_FOLLOW_DISTANCE_FULL : AVATAR_FOLLOW_DISTANCE;
    const height = CAMERA_HEIGHT + (fullBody ? 0.3 : 0.1);

    // 重用Vector3对象
    tempBackOffset.current.set(0, height, distance);
    // 相机直接跟随模型旋转，保持方向一致
    tempRot.current.set(0, targetRotation.y + Math.PI, 0);
    tempDesired.current.copy(targetPosition).add(tempBackOffset.current.applyEuler(tempRot.current));

    // 确保头部位置稳定，不受模型动画影响
    tempHead.current.set(targetPosition.x, targetPosition.y + 1.6, targetPosition.z);

    // 防遮挡：若线段(head->desired)穿过任一AABB，则将相机放在命中点前一点
    let bestT: number | null = null;
    for (const box of walls) {
      const t = segmentHitsAABB(tempHead.current, tempDesired.current, box);
      if (t !== null) {
        // 只有当碰撞点在合理范围内时才考虑
        if (t > 0.1 && t < 0.9) { // 避免在头部附近或目标点附近的碰撞
          if (bestT === null || t < bestT) bestT = t;
        }
      }
    }

    tempSafeDesired.current.copy(tempDesired.current);
    if (bestT !== null) {
      // 对遮挡比例做低通滤波，消除来回抖动
      const bias = 0.2; // 进一步增加偏置
      const clamped = Math.max(0.3, Math.min(1, bestT - bias)); // 确保最小距离
      const smoothedT = lastObstructionT.current == null ? clamped : (lastObstructionT.current * 0.8 + clamped * 0.2); // 进一步增加平滑度
      lastObstructionT.current = smoothedT;

      // 计算安全位置，但确保不会太靠近头部
      const safePosition = tempHead.current.clone().lerp(tempDesired.current, smoothedT);
      const minDistance = 0.5; // 最小距离保护
      const distanceFromHead = safePosition.distanceTo(tempHead.current);

      if (distanceFromHead >= minDistance) {
        tempSafeDesired.current.copy(safePosition);
      } else {
        // 如果距离太近，使用最小距离
        const direction = tempDesired.current.clone().sub(tempHead.current).normalize();
        tempSafeDesired.current.copy(tempHead.current).add(direction.multiplyScalar(minDistance));
      }
    }

    // 固定相机的垂直高度，避免上下跳动
    tempSafeDesired.current.y = tempDesired.current.y;

    if (!initialized.current) {
      smoothedPos.current.copy(tempSafeDesired.current);
      lastCameraPos.current.copy(smoothedPos.current);
      initialized.current = true;
    } else {
      // 适中响应速度，减小抢镜与漂移
      const lerpFactor = Math.min(1 - Math.pow(0.05, delta), 0.12); // 降低响应速度，增加平滑度
      smoothedPos.current.lerp(tempSafeDesired.current, lerpFactor);

      // 相机抖动抑制：限制相机移动速度
      cameraVelocity.current.copy(smoothedPos.current).sub(lastCameraPos.current);
      const velocityLength = cameraVelocity.current.length();

      if (velocityLength > maxCameraVelocity) {
        // 如果移动速度过快，限制到最大速度
        cameraVelocity.current.normalize().multiplyScalar(maxCameraVelocity);
        smoothedPos.current.copy(lastCameraPos.current).add(cameraVelocity.current);
      }

      lastCameraPos.current.copy(smoothedPos.current);
    }

    camera.position.copy(smoothedPos.current);
    camera.lookAt(tempHead.current);
  });

  return null;
};

// 信息面板组件
const InfoPanel: React.FC<{
  selectedExhibit: string | null;
  onClose: () => void;
}> = ({ selectedExhibit, onClose }) => {
  if (!selectedExhibit) return null;

  // 仓库场景不展示这些旧的展品条目，留空
  const exhibitInfo: { [key: string]: { title: string; description: string; artist: string } } = {};

  const info = exhibitInfo[selectedExhibit];
  if (!info) return null;

  return (
    <div className="info-panel">
      <div className="info-content">
        <button className="close-btn" onClick={onClose}>×</button>
        <h3>{info.title}</h3>
        <p className="artist">{info.artist}</p>
        <p className="description">{info.description}</p>
      </div>
    </div>
  );
};

// 主页面组件
const LookPage: React.FC = () => {
  const navigate = useNavigate();
  const [audioRef, setAudioRef] = useState<HTMLAudioElement | null>(null);
  const [isTTSBusy, setIsTTSBusy] = useState(false);
  // 注意：此处变量名保持不变，但它们现在代表“主角位置/朝向”
  const [cameraPosition, setCameraPosition] = useState(new Vector3(15, 0, 0));
  const [cameraRotation, setCameraRotation] = useState(new Euler(0, 0, 0));
  const [selectedExhibit, setSelectedExhibit] = useState<string | null>(null);
  const [showInstructions, setShowInstructions] = useState(true);
  const [fullBodyView, setFullBodyView] = useState(true);
  // 迷宫相关状态已移除
  // 卷帘门交互状态
  const DOOR_CENTER = useMemo(() => ({ x: 0, z: -19.6 }), []); // 前墙中部
  const [isPlayerMoving, setIsPlayerMoving] = useState(false);
  const [isPlayerRunning, setIsPlayerRunning] = useState(false);
  const [leftTurnTick, setLeftTurnTick] = useState(0);
  const [rightTurnTick, setRightTurnTick] = useState(0);
  const [jumpTick, setJumpTick] = useState(0);
  const [isJumping, setIsJumping] = useState(false);
  const [isOnGround, setIsOnGround] = useState(true); // 添加地面检测状态
  const [isPlayerBackward, setIsPlayerBackward] = useState(false);
  const corridorArtworks = useMemo(() => {
    // 动态引入 src/img 下的所有图片文件（带原始文件名）
    const modules = import.meta.glob('../../img/*.{png,jpg,jpeg,gif,webp}', { eager: true }) as Record<string, { default: string }>;
    const assets = Object.keys(modules)
      .sort()
      .map(k => {
        const url = modules[k]?.default;
        const filename = k.split('/').pop() || k;
        const nameNoExt = filename.replace(/\.[^.]+$/, '');
        const title = decodeURIComponent(nameNoExt);
        return { url, title };
      })
      .filter(a => !!a.url && !a.title.toLowerCase().includes('笑脸') && !a.title.toLowerCase().includes('smile') && !a.title.toLowerCase().includes('face')) as { url: string; title: string }[];

    // 布局：优先沿右侧外墙（z 从 -12 到 12，间隔 4），再沿底部外墙（x 从 -12 到 12，间隔 4）
    const positions: Array<{ position: [number, number, number]; rotation: [number, number, number] }> = [];
    const y = 2.5;
    // 让展品紧贴墙面：右墙在x=20，后墙在z=20，展品应该贴在墙面上
    const rightX = 19.6; // 紧贴右墙（x=20）的内侧
    const bottomZ = 19.6; // 紧贴后墙（z=20）的内侧

    const rightSpots = [-12, -8, -4, 0, 4, 8, 12].map(z => ({ position: [rightX, y, z] as [number, number, number], rotation: [0, -Math.PI / 2, 0] as [number, number, number] }));
    const bottomSpots = [-12, -8, -4, 0, 4, 8, 12].map(x => ({ position: [x, y, bottomZ] as [number, number, number], rotation: [0, Math.PI, 0] as [number, number, number] }));
    positions.push(...rightSpots, ...bottomSpots);

    const items: { position: [number, number, number]; rotation: [number, number, number]; url: string; title: string }[] = [];
    assets.forEach((asset, i) => {
      const spot = positions[i % positions.length];
      items.push({ position: spot.position, rotation: spot.rotation, url: asset.url, title: asset.title });
    });
    return items;
  }, []);

  // 计算迷宫墙体AABB（仅XZ平面）
  const [, walls, , exitPoint, entranceDoor, corridorEntrance] = useMemo(() => {
    // 去除迷宫：仅保留外墙的碰撞盒
    const inflate = 0.12; // 减少碰撞盒膨胀，降低敏感度
    const aabbs: WallAABB[] = [];
    // 外墙四周
    aabbs.push({ minX: -20, maxX: -19.2, minZ: -20, maxZ: 20 });
    aabbs.push({ minX: 19.2, maxX: 20, minZ: -20, maxZ: 20 });
    aabbs.push({ minX: -20, maxX: 20, minZ: -20, maxZ: -19.2 });
    aabbs.push({ minX: -20, maxX: 20, minZ: 19.2, maxZ: 20 });
    // 中排立柱已删除 - 碰撞检测已移除

    // 八边形中央平台碰撞检测 (0, 0, 0)
    aabbs.push({ minX: -2.6 - inflate, maxX: 2.6 + inflate, minZ: -2.6 - inflate, maxZ: 2.6 + inflate });

    // 中央圆形平台外围墙壁碰撞检测
    // 左墙碰撞检测 - 面向右墙的墙壁，延长创造更大空间
    aabbs.push({ minX: -9.1 - inflate, maxX: -8.9 + inflate, minZ: -13 - inflate, maxZ: 13 + inflate });
    // 右墙碰撞检测 - 面向左墙的墙壁，延长创造更大空间
    aabbs.push({ minX: 8.9 - inflate, maxX: 9.1 + inflate, minZ: -13 - inflate, maxZ: 13 + inflate });
    // 后墙碰撞检测 - 长度延伸连接左右墙壁，创造更宽阔空间
    aabbs.push({ minX: -9 - inflate, maxX: 9 + inflate, minZ: 6.9 - inflate, maxZ: 7.1 + inflate });

    // 悬浮矩形棱镜碰撞检测 (0, 2.5, 0) - 仅XZ平面
    aabbs.push({ minX: -2.0 - inflate, maxX: 2.0 + inflate, minZ: -0.4 - inflate, maxZ: 0.4 + inflate });

    // 现代会议室家具碰撞检测
    // 长会议桌碰撞检测
    aabbs.push({ minX: -4.0 - inflate, maxX: 4.0 + inflate, minZ: -10.25 - inflate, maxZ: -8.75 + inflate });

    // 会议椅碰撞检测 - 左侧椅子
    [-3, -2, -1, 0, 1, 2, 3].forEach(x => {
      aabbs.push({ minX: x - 0.3 - inflate, maxX: x + 0.3 + inflate, minZ: -11.8 - inflate, maxZ: -11.2 + inflate });
    });

    // 会议椅碰撞检测 - 右侧椅子
    [-3, -2, -1, 0, 1, 2, 3].forEach(x => {
      aabbs.push({ minX: x - 0.3 - inflate, maxX: x + 0.3 + inflate, minZ: -7.8 - inflate, maxZ: -7.2 + inflate });
    });


    // 绿色植物碰撞检测
    aabbs.push({ minX: 7.7 - inflate, maxX: 8.3 + inflate, minZ: 2.7 - inflate, maxZ: 3.3 + inflate });

    // 发光圆柱柱体碰撞检测 (-6, 0, 0) - 调整位置避免穿模
    aabbs.push({ minX: -6.8 - inflate, maxX: -5.2 + inflate, minZ: -0.8 - inflate, maxZ: 0.8 + inflate });

    // 现代展厅桌子碰撞检测 (6, 0, -6)
    aabbs.push({ minX: 5.0 - inflate, maxX: 7.0 + inflate, minZ: -6.6 - inflate, maxZ: -5.4 + inflate });

    // 小房间碰撞检测已移除 - 玩家可以自由穿过

    // 大房间背后区域床的碰撞检测 - 床面向前墙
    aabbs.push({ minX: -5.8 - inflate, maxX: -2.2 + inflate, minZ: 7.9 - inflate, maxZ: 11.1 + inflate });

    // 床边木制桌子碰撞检测 - 豪华大桌子
    aabbs.push({ minX: -5.0 - inflate, maxX: -3.0 + inflate, minZ: 11.9 - inflate, maxZ: 13.1 + inflate });

    // 现代桌椅组合碰撞检测 - 屏风旁边 - 加长版精准碰撞
    aabbs.push({ minX: 3.0 - inflate, maxX: 5.0 + inflate, minZ: 8.4 - inflate, maxZ: 10.6 + inflate });

    // 灰色抽屉柜碰撞检测 - 复刻版 - 桌椅旁边 - 前移后
    aabbs.push({ minX: 4.7 - inflate, maxX: 6.3 + inflate, minZ: 7.8 - inflate, maxZ: 9.2 + inflate });

    // 四面板屏风碰撞检测 - 床旁边
    aabbs.push({ minX: 0.0 - inflate, maxX: 2.0 + inflate, minZ: 8.5 - inflate, maxZ: 10.5 + inflate });

    // 灰色抽屉柜碰撞检测 - 贴着床房间左墙
    aabbs.push({ minX: -9.1 - inflate, maxX: -7.9 + inflate, minZ: 8.3 - inflate, maxZ: 10.7 + inflate });

    // 出生点：走廊边
    const spawnPoint = { x: 15, z: 0 };
    const exitPt = null; // 不再使用
    const entrance = null; // 不再使用
    const corridor = null; // 不再使用
    return [[], aabbs, spawnPoint, exitPt, entrance, corridor] as const;
  }, []);

  // 展品交互已移除

  // 确保初始位置在走廊边
  useEffect(() => {
    setCameraPosition(new Vector3(15, 0, 0));
    setCameraRotation(new Euler(0, 0, 0));
  }, []);

  useEffect(() => {
    // 3秒后隐藏操作说明
    const timer = setTimeout(() => {
      setShowInstructions(false);
    }, 3000);

    return () => clearTimeout(timer);
  }, []);

  // 计算是否靠近门，提示并允许按 E 交互
  const nearDoor = Math.hypot(cameraPosition.x - DOOR_CENTER.x, cameraPosition.z - DOOR_CENTER.z) < 2.2;
  useEffect(() => {
    const onKey = () => {
      // 门交互已移除，现在门是静态的科技门
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [nearDoor]);

  const handleJump = () => {
    // 只有在没有跳起且在地面上时才允许跳起
    if (!isJumping && isOnGround) {
      setIsJumping(true);
      setIsOnGround(false); // 跳起时离开地面
      setJumpTick(t => t + 1);
    }
  };

  const handleJumpFinished = useCallback(() => {
    setIsJumping(false);
    setIsOnGround(true); // 跳跃结束，回到地面
    setJumpTick(0);
  }, []);

  const handleSpeak = async (text: string) => {
    console.log('handleSpeak 被调用，文本:', text);
    try {
      // 若正在播放或正在合成，直接忽略点击，等上一次播报结束
      if ((audioRef && !audioRef.ended && !audioRef.paused) || isTTSBusy) {
        console.log('语音正在播放中，跳过');
        return;
      }
      console.log('开始TTS合成...');
      setIsTTSBusy(true);
      const blob = await synthesizeSpeech(text);
      console.log('TTS合成完成，开始播放');
      const url = URL.createObjectURL(blob);
      const player = new Audio(url);
      player.onended = () => {
        console.log('语音播放结束');
        URL.revokeObjectURL(url);
        setAudioRef(null);
      };
      await player.play();
      setAudioRef(player);
      console.log('语音播放开始');
    } catch (e) {
      console.error('TTS 播放失败:', e);
      alert('语音播放失败，请在百度控制台添加 http://localhost:5173 为白名单后重试');
    }
    finally {
      setIsTTSBusy(false);
    }
  };

  console.log('=== Look页面渲染调试信息 ===');
  console.log('showInstructions:', showInstructions);
  console.log('cameraPosition:', cameraPosition);
  console.log('cameraRotation:', cameraRotation);
  console.log('isPlayerMoving:', isPlayerMoving);
  console.log('isPlayerRunning:', isPlayerRunning);
  console.log('fullBodyView:', fullBodyView);
  console.log('========================');

  console.log('LookPage 渲染开始');
  console.log('cameraPosition:', cameraPosition);
  console.log('cameraRotation:', cameraRotation);
  console.log('walls:', walls);
  console.log('exitPoint:', exitPoint);
  console.log('entranceDoor:', entranceDoor);
  console.log('corridorArtworks:', corridorArtworks);

  return (
    <div className="look-page">
      {/* 退出按钮 */}
      <button
        className="exit-button"
        onClick={() => navigate('/mySelf')}
        title="退出展览馆"
      >
        ✕ 退出展览馆
      </button>

      {/* 操作说明 */}
      {showInstructions && (
        <div className="instructions">
          <h3>操作说明</h3>
          <p>WASD - 移动 | 鼠标拖拽 - 视角控制 | F - 切换视角模式 | 空格 - 跳起</p>
          <p>在场馆内自由探索，欣赏展品</p>
        </div>
      )}

      {/* 3D场景 */}
      <div className="canvas-container">
        <Canvas
          camera={{ position: [15, 0, 0], fov: 75 }}
          shadows={{ type: THREE.BasicShadowMap }}
          dpr={[1, 1.25]}
          gl={{ antialias: true, alpha: true, powerPreference: 'high-performance' }}
          style={{ width: '100%', height: '100%' }}
          onCreated={({ gl, scene, camera }) => {
            console.log('Canvas创建成功:', { gl, scene, camera });
          }}
        >
          {/* 现代展厅背景色 - 纯白现代风格 */}
          <color attach="background" args={["#ffffff"]} />
          <FirstPersonController
            position={cameraPosition}
            rotation={cameraRotation}
            onPositionChange={setCameraPosition}
            onRotationChange={setCameraRotation}
            walls={walls}
            onToggleFullBody={() => setFullBodyView(v => !v)}
            onMovementChange={setIsPlayerMoving}
            onRunChange={setIsPlayerRunning}
            onBackwardChange={setIsPlayerBackward}
            onLeftTurn={() => setLeftTurnTick(t => t + 1)}
            onRightTurn={() => setRightTurnTick(t => t + 1)}
            onJump={handleJump}
          />
          <CameraRig
            targetPosition={cameraPosition}
            targetRotation={cameraRotation}
            fullBody={fullBodyView}
            walls={walls}
          />
          <ExhibitionHall exitPoint={exitPoint} entranceDoor={entranceDoor} corridorEntrance={corridorEntrance} corridorArtworks={corridorArtworks} onSpeak={handleSpeak} />
          <AvatarFollower
            cameraPosition={cameraPosition}
            cameraRotation={cameraRotation}
            modelUrl={AVATAR_URL}
            isMoving={isPlayerMoving}
            isRunning={isPlayerRunning}
            isBackward={isPlayerBackward}
            leftTurnTick={leftTurnTick}
            rightTurnTick={rightTurnTick}
            jumpTick={jumpTick}
            isJumping={isJumping}
            isOnGround={isOnGround}
            onJumpFinished={handleJumpFinished}
          />
        </Canvas>
      </div>

      {/* 信息面板 */}
      <InfoPanel
        selectedExhibit={selectedExhibit}
        onClose={() => setSelectedExhibit(null)}
      />


      {/* 入口提示已移除 */}

      {/* 出口提示已移除 */}

      {/* 控制提示 */}
      <div className="controls-hint">
        <div className="control-item">
          <span className="key">W</span>
          <span>前进</span>
        </div>
        <div className="control-item">
          <span className="key">S</span>
          <span>后退</span>
        </div>
        <div className="control-item">
          <span className="key">A</span>
          <span>左移</span>
        </div>
        <div className="control-item">
          <span className="key">D</span>
          <span>右移</span>
        </div>
        <div className="control-item">
          <span className="key">鼠标</span>
          <span>视角</span>
        </div>
        <div className="control-item" onClick={() => setFullBodyView(v => !v)} style={{ cursor: 'pointer' }}>
          <span className="key">F</span>
          <span>{fullBodyView ? '贴背视角' : '全身视角'}</span>
        </div>
        <div className="control-item">
          <span className="key">空格</span>
          <span>跳起</span>
        </div>
      </div>

    </div>
  );
};

export default LookPage;